使用指针将struct转换为char数组

时间:2017-11-15 06:20:11

标签: c

我目前正在尝试找到将包含char *的struct转换为char数组以传输串行数据帧的最简单方法。

struct存储帧头,校验和,msg大小等以及要传输的数据。例如

struct {
    unsigned char header;
    unsigned char msgSizeL;
    unsigned char msgSizeH;
    unsigned char *data;
    unsigned char checksum;
    ....
    ....
    ....
    ....
    unsinged char endFrame;
} Frame;

数据是指针,因为每帧传输的数据量可以在1到16个字节的范围内变化。

我试图找到将结构转换为无符号字符数组的最简单方法,而不将结构中的每个条目复制到数组中,但似乎无法找到方法。

或者我不必使用结构,因为我生成的框架内容从头开始排除数据内容,我只是想避免一个案例 -

unsigned char frame[1000];
frame[0] = 0x01; // header
frame[1] = msgSizeL; // msg size low byte
frame[2] = msgSizeH; // msg size high byte
frame[3] = data[0]; // data contents 0    Over simplification
frame[4] = data[1]; // data contents 1    for data copying - 
frame[5] = data[2]; // data contents 2    data length is variable.
frame[6] = data[3]; // data contents 3
frame[7] = data[4]; // data contents 4
frame[8] = data[5]; // data contents 5
frame[9] = data[6]; // data contents 6
frame[10] = data[7]; // data contents 7
frame[3 + msgSize]; = getChecksum(data);
....
....
....
....
frame [3 + msgSize + 20] = 0xFF; // end frame

我将数据写入读取为随机数组索引的内容,而不是像frame.checksum = getChecksum(data);那样有意义的内容。

对于提出一般性问题而非具体问题,可以提出建议和一点点火焰: - )

2 个答案:

答案 0 :(得分:0)

  

我试图找到将结构转换为无符号字符数组的最简单方法,而不将结构中的每个条目复制到数组中,但似乎无法找到方法。

如果data最多包含16个字节,我只需将其声明为16-char数组,如下所示:

#define MAX_DATA_LEN 16
struct {
    unsigned char header;
    unsigned char msgSizeL;
    unsigned char msgSizeH;
    unsigned char data[MAX_DATA_LEN]; // 16-char array instead of pointer
    unsigned char checksum;
    ....
    ....
    ....
    ....
    unsinged char endFrame;
} Frame;

如果这样做,那么这个结构中的所有数据都有一个预定义的大小(即unsigned char * sizeof(unsigned char)的数量,依此类推其他数据类型......)你可以使用简单的{{1将结构复制到数组:

memcpy

答案 1 :(得分:0)

您有两种选择:

<强> 1。动态帧长

struct {
    unsigned char header;
    unsigned char msgSizeL; // this will be dynamic from 0x06 (empty) to 0x16 (full)
    unsigned char msgSizeH; // this will be always 0x00
    unsigned char dataSize; // specify the data size here
    unsigned char data[16]; // use a static memory area for the package
    unsigned char checksum;
    unsigned char endFrame;
} Frame;

然后你可以这样做:

Frame xFrame;
unsigned char ucaData[17] = {0}; // your data 
unsigned int uiDataLength = 6; // for example
memset(&xFrame, 0, sizeof(Frame)); // just to be sure
xFrame.header = 0x01;
xFrame.msgSizeL = uiDataLength;
xFrame.msgSizeH = 0;
xFrame.dataSize = uiDataLength;
memcpy(xFrame.data, ucaData, uiDataLength);
xFrame.checksum = CRC8(&xFrame, uiDataLength + 4); // crc for filled area
xFrame.endFrame = 0xFF;

然后在构建包时:

unsigned char xDataFrame[1000];
memcpy(xDataFrame, xFrame, 4 + uiDataLength);
memcpy(xDataFrame + 4 + uiDataLength, &xFrame + 20, 2);
transmit(xDataFrame, 6 + uiDataLength);

这样,您将丢弃发送和计算校验和的空字节。

<强> 2。静态帧长

然后你可以使用这样的结构:

struct {
    unsigned char header;
    unsigned char msgSizeL; // this will be always 0x16 (22)
    unsigned char msgSizeH; // this will be always 0x00
    unsigned char dataSize; // specify the data size here
    unsigned char data[16]; // use a static memory area for the package
    unsigned char checksum;
    unsigned char endFrame;
} Frame;

通过这种方式,您可以计算此结构的前20个字节的校验和,但请注意,此结构可能包含填充区域,这些填充区域可能会在定义的和填充的内存区域周围移动数据。 sizeof(Frame)可以手动计算为22个字节,但编译器可以决定它应该使用与pack设置相关的32个字节或24个字节的内存。你可以使用

#pragma pack(1) // disable padding
[structure code]
#pragma pack()  // back to the original setting

有关包装的更多信息:

#pragma pack effect