我在 C 語言中相對較新,我在緩沖區中存盤結構時遇到了一些問題;
我有這個結構:
`typedef struct {
uint8_t size_of_payload;
uint8_t command;
unsigned char* payload;
}__attribute__((packed)) mystruct``
我想在 tx_buffer[SIZE] 中復制這個結構的值,包括有效載荷指向的值。payload 指向一個大小等于 size_of_payload 的 char 陣列。
memcpy(&tx_buffer,&mystruct,sizeof(mystruct));
僅復制有效載荷地址的值。
有可能這樣做嗎?
uj5u.com熱心網友回復:
好吧,不可能通過一個簡單的電話來做到這一點。您將不得不“手動”進行操作。memcpy 只能將一個記憶體區域復制到另一個記憶體區域。您的源記憶體區域的結構不是您希望在目的地的方式,因此必須手動進行。我們先復制前兩個欄位
memcpy(&tx_buffer 0*sizeof(uint8_t),&mystruct.size_of_payload, 1*sizeof(uint8_t));
memcpy(&tx_buffer 1*sizeof(uint8_t),&mystruct.command, 1*sizeof(uint8_t));
我們在這里所做的是將第一個元素復制到 tx_buffer 的位置 0,然后將第二個元素復制到 1 位元組的位置。對于字串,我們不知道長度。我們可以找到它并執行 memcpy,但有一個方便的替代方法:
strcpy(&tx_buffer 2*sizeof(uint8_t), mystruct.payload)
uj5u.com熱心網友回復:
由于該結構包含一個作為指標的成員(間接級別),因此不能一次性完成。
在這種特殊情況下(因為指標是最后一個成員),方法是:
- 復制結構的內容直到指標成員
- 復制取消參考的指標成員的內容(基于大小成員)
請注意,對于更復雜的結構,具有交替的指標和常規成員,您需要對相同型別的第一個成員進行一次memcpy呼叫 對每個連續成員型別(正常 -> 指標,指標 - > 正常,指標 -> 指標)。
代碼00.c
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define BUF_DIM 0xFF // Make sure it's large enough
typedef struct {
uint8_t size_of_payload;
uint8_t command;
unsigned char *payload;
} __attribute__((packed)) Data;
size_t dataSize(const Data *pData)
{
if (pData == NULL)
return 0;
return offsetof(Data, payload) pData->size_of_payload;
}
size_t copyData(const Data *pData, uint8_t *pBuf)
{
size_t sz = dataSize(pData);
if (sz == 0)
return 0;
size_t ofs = offsetof(Data, payload);
memcpy(pBuf, pData, ofs);
memcpy(pBuf ofs, pData->payload, pData->size_of_payload);
return sz;
}
int main()
{
unsigned char array[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'c', 'd' };
Data data = { sizeof(array), 123, array };
uint8_t buf[BUF_DIM] = { 0 };
copyData(&data, buf);
size_t ds = dataSize(&data);
printf("Size: %ld\nBuf:\n", ds);
for (size_t i = 0; i < ds; i)
printf("0xX(%c) ", buf[i], buf[i]);
printf("\nDone.\n");
return 0;
}
輸出:
(qaic-env) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q071451221]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [064bit prompt]> ls main00.c [064bit prompt]> gcc -o main00.exe main00.c [064bit prompt]> ./main00.exe Size: 16 Buf: 0x0E() 0x7B({) 0x30(0) 0x31(1) 0x32(2) 0x33(3) 0x34(4) 0x35(5) 0x36(6) 0x37(7) 0x38(8) 0x39(9) 0x41(A) 0x42(B) 0x63(c) 0x64(d) Done.
uj5u.com熱心網友回復:
使用靈活的陣列成員。您將擁有更簡單的代碼:
typedef struct {
uint8_t size_of_payload;
uint8_t command;
uint8_t payload[];
} mystruct;
分配一個結構:
mystruct *allocMyStruct( uint_8 command, uint8_t size, uint8_t *payload )
{
mystruct *m = malloc( sizeof( *m ) size );
m->size_of_payload = size;
m->command = command;
memcpy( m->payload, payload, size );
return( m )
}
復制:
mystruct *m = ...
.
.
.
// copy *ALL* the fields and the payload
memcpy( txBuffer, m, sizeof( *m ) m->size_of_payload );
釋放結構:
mystruct *m = ...
.
.
.
free( m );
靈活陣列成員的唯一缺點是您不能將它們分配為區域或靜態變數。
你不能做
mystruct m;
當您使用靈活的陣列成員時。
但與結構中幾乎必須動態分配的uint_t *payload 指標相比,實際上并沒有失去靈活性。
在這種情況下,沒有理由不使用靈活的陣列成員。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/441993.html
