缓冲区中的c-memcpy复杂结构



我在C语言中相对较新,在缓冲区中记忆结构时遇到了一些问题;

我有这样的结构:

`typedef struct {
uint8_t size_of_payload;
uint8_t command;
unsigned char* payload;
}__attribute__((packed)) mystruct``

我想在tx_buffer[SIZE]中复制这个结构的值,包括payload指向的值。payload指向一个大小等于size_of_epayload的char数组。

memcpy(&tx_buffer,&mystruct,sizeof(mystruct));

仅复制有效负载地址的值。

有可能这样做吗?

不可能在一个简单的调用中完成。您将不得不"手动"执行此操作。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的零位置,将第二个元素复制到此之后的1字节位置。对于字符串,我们不知道长度。我们可以找到它并进行memcpy,但有一个方便的替代方案:

strcpy(&tx_buffer+2*sizeof(uint8_t), mystruct.payload)

整个设置对我来说似乎有点奇怪;"压平";结构?或者,如果需求是合理的,为什么选择这种结构布局?无论如何,我会尝试举例说明(我认为(最简单的方法(从其他标准来看,这不是最好的(。

由于该结构包含一个作为指针(间接级别(的成员,因此不能一次性完成
在这种特殊情况下(因为指针是最后一个成员(,方法是:

  1. 将结构的内容复制到指针成员
  2. 复制取消引用的指针成员的内容(基于大小成员(

请注意,对于更复杂的结构,使用交替的指针和常规成员,您需要对同一类型的1st成员进行一次memcpy调用,对每个连续的成员类型(normal->pointerpointer->normalpointer-&>;pointer-(进行一次额外调用。

code00.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: %ldnBuf:n", ds);
for (size_t i = 0; i < ds; ++i)
printf("0x%02X(%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.

使用灵活的数组成员。你会有更简单的代码:

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指针相比,实际上并没有失去灵活性。

在这种情况下,没有理由不使用灵活的数组成员。

最新更新