C语言中具有动态内存分配的结构

C语言中具有动态内存分配的结构,c,memory,dynamic,allocation,realloc,C,Memory,Dynamic,Allocation,Realloc,我需要将数据写入一个结构,其中数据的长度取决于我要发送给设备的命令。为此,我定义了以下结构: typedef struct { uint8 len; // Command length (cmd ... crc) uint8 cmd; // Command code uint8 data_length; // Data length uint8 data[12]; // Data: max 12 Byte ui

我需要将数据写入一个结构,其中数据的长度取决于我要发送给设备的命令。为此,我定义了以下结构:

typedef struct {
    uint8 len;          // Command length (cmd ... crc)
    uint8 cmd;          // Command code
    uint8 data_length;  // Data length
    uint8 data[12];     // Data: max 12 Byte
    uint8 crc_h;        // CRC value MSB
    uint8 crc_l;        // CRC value LSB
}CMD_TYPE;
注意:始终存在的成员cmd、*data_length*和crc,而成员数据可以是空的或最多包含12个字节

我创建了一个函数,该函数根据传递给该函数的参数返回初始化命令:

CMD_TYPE Device::get_cmd(uint8 cmd, uint8 data_len, uint8 *data)
{
    CMD_TYPE cmd;

    cmd.len = (4 + data_len) * sizeof(uint8);
    cmd.cmd = cmd;
    cmd.data_length = data_len;
    cmd.data = (uint8 *)realloc(cmd.data, data_len*sizeof(uint8));
    if(data_len > 0)    memcpy(cmd.data, data, data_len);

    add_crc16((uint8*)&cmd);

    return cmd;
}
函数get_cmd()的用法如下:

uint8 cmd_code = 0x01;
uint8 data[2] = {0xAB, 0xCD};

CMD_TYPE cmd = local_device->get_cmd(cmd_code, 2, data);
retVal = local_device->send(cmd);
当我试图编译这段代码时,我从该行的编译器中得到一个错误:

cmd.data = (uint8 *)realloc(cmd.data, data_len*sizeof(uint8));
编译器错误是:

error: lvalue required as left operand of assignment

使用realloc()的目的是重新调整数组数据的大小,或者将其从新的命令结构中删除。我的代码有什么问题?这是使用动态内存分配初始化结构的正确方法吗?

定义为[…]的数组是不可变的,您不能为它们分配任何内容。相反,您应该使用指针。

定义为[…]的数组是不可变的,您不能为它们分配任何内容。相反,您应该使用指针。

您的
CMD\u类型。数据是数组,而不是指针。因为您希望它跟踪动态分配的内存,所以它必须是指针:

uint8_t * data;
只是别忘了用
malloc()
(或者在
realloc()
之前将其设置为零)初始化它,然后自己清理


顺便说一下,不要强制转换
malloc()
和co的结果。

您的
CMD\u类型。数据是数组,而不是指针。因为您希望它跟踪动态分配的内存,所以它必须是指针:

uint8_t * data;
只是别忘了用
malloc()
(或者在
realloc()
之前将其设置为零)初始化它,然后自己清理


顺便说一句,不要对malloc()和co.的结果施加影响。

你想要的是臭名昭著的:

诀窍是为结构的所有成员分配足够的空间,直到
data[]
,然后为
data[]
成员添加足够的字节:

CMD_TYPE * allocCmd(int dataSize)
{
    int         len;
    CMD_TYPE *  p;

    len = sizeof(CMD_TYPE) + (dataSize-1)*sizeof(uint8);
    p = (CMD_TYPE *) malloc(len);
    memset(p, 0, len);
    p->data_length = dataSize;
    return p;
}
在这里,
len
被计算为结构的大小,减去空
data
成员的大小,再加上
dataSize
data
数组指定的元素数量


需要注意的是,您必须小心不要访问
p->data[]
中实际分配的元素之外的任何元素(在结构内部)。

您想要的是臭名昭著的:

诀窍是为结构的所有成员分配足够的空间,直到
data[]
,然后为
data[]
成员添加足够的字节:

CMD_TYPE * allocCmd(int dataSize)
{
    int         len;
    CMD_TYPE *  p;

    len = sizeof(CMD_TYPE) + (dataSize-1)*sizeof(uint8);
    p = (CMD_TYPE *) malloc(len);
    memset(p, 0, len);
    p->data_length = dataSize;
    return p;
}
在这里,
len
被计算为结构的大小,减去空
data
成员的大小,再加上
dataSize
data
数组指定的元素数量


需要注意的是,您必须小心不要访问
p->data[]
中实际分配的元素之外的任何元素(在结构内部).

数组不是指针-不能重新分配数组的内存位置。数组不是指针-不能重新分配数组的内存位置。他为什么不强制转换
malloc()的结果?它返回一个void*,no?因为在C中不强制转换-如果这样做,可能会隐藏错误,而C显式允许您使用这样的void指针。另外,它看起来不是很难看吗?谢谢你的快速回复!我已经做了更改,现在当data_length为0时,一切似乎都是正确的。但当我想将数据写入字段数据时,数据似乎没有正确复制。这里是我的更改:
cmd.data=(uint8*)malloc(data_len*sizeof(uint8))注意:如果我没有强制转换结果,编译器将返回错误:
错误:从'void*'到'uint8*'的转换无效。
@imx:您现在需要一些额外的代码来正确初始化结构并清理它。这不仅仅是一句话的改变。也许你没有在你使用的语言上对我们直言不讳。C(我指的是“isoc标准”)明确允许从void指针进行转换。如果你使用的是非标准编译器或方言(Borland Turbo C从1985?MS VisualC++),请适当地标记问题。请注意,C++与C不一样,微软没有真正的C编译器。为什么他不能把 MalCube()/<代码>的结果?它返回一个void*,no?因为在C中不强制转换-如果这样做,可能会隐藏错误,而C显式允许您使用这样的void指针。另外,它看起来不是很难看吗?谢谢你的快速回复!我已经做了更改,现在当data_length为0时,一切似乎都是正确的。但当我想将数据写入字段数据时,数据似乎没有正确复制。这里是我的更改:
cmd.data=(uint8*)malloc(data_len*sizeof(uint8))注意:如果我没有强制转换结果,编译器将返回错误:
错误:从'void*'到'uint8*'的转换无效。
@imx:您现在需要一些额外的代码来正确初始化结构并清理它。这不仅仅是一句话的改变。也许你没有在你使用的语言上对我们直言不讳。C(我指的是“isoc标准”)明确允许从void指针进行转换。如果你使用的是非标准编译器或方言(Borland Turbo C从1985?MS VisualC++),请适当地标记问题。请注意,C++与C不一样,微软没有真正的C编译器。是的,这样的结构会更容易。但问题是,我必须严格按照我在结构中的顺序发送数据。@imx51,您只能更改结构末尾的数据。不能改变结构内数据的大小。您可以使数据成为指向另一个长度不同的结构/数组的指针(因为指针本身不会改变大小),您也可以使用这个