c 结构体中的零长数组

有零长度数组成员的结构体,通常可以为我们定义变长结构体,方便程序数据的传输和修改。但是通常只能在最后一个字段扩展开来。但是大多数协议或者数据结构的结构体中最后一个字节通常用来作为校验位计算。所以不方便使用0长度数组的成员。但是我们可以通过定义结构体的函数处理这种情况,下面是我的记录。

#include <iostream>
#include <cstring>
#include <stdint.h>

typedef struct _A
{
    uint8_t nametype;
    uint8_t len;
    uint8_t data[0];
    uint8_t sum;
public:
    void CalSum()
    {
        uint8_t* sumptr = (&(sum)+len);
        *sumptr ^= nametype;
        *sumptr ^= len;
        for(int i=0;i<len+sizeof(_A);++i)
            *sumptr ^= (data[i]);
    }
    
    static _A* New(uint32_t datasize)
    {
        _A* newer = static_cast<_A*>(std::malloc(sizeof(_A)+datasize));
        newer->len = datasize;
        std::memset(newer,0,sizeof(_A)+datasize);
        return newer;
    }
    
} *STRUCT_A;
 


int main()
{
    //随便定义长度
    int allocLen = 3;
    STRUCT_A temp = _A::New(allocLen);
    temp->nametype = 97;
    

    //设置测试数据 [0] = 'A' [1] = 'B'  [2] = 'C'
    for(int i=0;i<allocLen;++i)
        (temp->data[i] = i+65); //由于我们这里是定义0长度数组 data[0] 即会覆盖sum的值了。
        
    for(int j=0; j< (sizeof(_A)+allocLen); ++j)
        std::cout << std::hex << ((uint8_t*)(temp))[j] << std::endl;
    
    //最后再来计算检验和。
    temp->CalSum();
         
    std::cout  << "### sum ="  << (uint)(temp->sum) << std::endl;
    
    //顺序打印结构体内存布局
    for(int j=0; j< (sizeof(_A)+allocLen); ++j)
        std::cout << std::hex << ((uint8_t*)(temp))[j] << std::endl;
}