Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 联合结构中的额外数据元素_C++_Arrays_Structure_Unions - Fatal编程技术网

C++ 联合结构中的额外数据元素

C++ 联合结构中的额外数据元素,c++,arrays,structure,unions,C++,Arrays,Structure,Unions,我试图将一个相对复杂的消息编码到一个联合结构中,这样我就可以生成一个uint8_t数组,并将其输入到串行通信协议中 但是,当查看在我的union中填充数据时生成的数组时,在我的命令类型元素之后会出现一个额外的uint8\u t元素。请参见下面的工会结构: union myint16_t{ uint16_t ui16; int16_t i16; uint8_t data[2]; }; union { struct {

我试图将一个相对复杂的消息编码到一个联合结构中,这样我就可以生成一个uint8_t数组,并将其输入到串行通信协议中

但是,当查看在我的union中填充数据时生成的数组时,在我的命令类型元素之后会出现一个额外的uint8\u t元素。请参见下面的工会结构:

union myint16_t{
        uint16_t ui16;
        int16_t i16;
        uint8_t data[2];
    };

union {
    struct {
        uint8_t commandtype;
        myint16_t UpperLimits[4];
        myint16_t LowerLimits[4];
        myint16_t JointZeros[4];
        int8_t JointPolarity[4];
        myint16_t P[4];
        myint16_t I[4];
        myint16_t D[4];

    };
    uint8_t data[53];
};
如您所见,第二个匿名联合引用了联合myint16\t。 因此,如果我填充匿名联合的所有值,然后打印出基础数据[53]数组,那么我的第二个值(数据[1])是0,而不是上限[4]的第一个元素的一部分。请参阅代码,我在其中填充联合体,然后打印出元素

char q = 'c';



    hmmv4_configmsg msg;

msg.commandtype =(uint8_t) q;
msg.UpperLimits[0].ui16 = 784;
msg.UpperLimits[1].ui16  = 784;
msg.UpperLimits[2].ui16  = 784;
msg.UpperLimits[3].ui16  = 784;
msg.LowerLimits[0].ui16  = 223;
msg.LowerLimits[1].ui16  = 223;
msg.LowerLimits[2].ui16  = 223;
msg.LowerLimits[3].ui16  = 223;
msg.JointZeros[0].ui16  = 512;
msg.JointZeros[1].ui16  = 512;
msg.JointZeros[2].ui16  = 512;
msg.JointZeros[3].ui16  = 512;
msg.JointPolarity[0] = -1;
msg.JointPolarity[1] =-1;
msg.JointPolarity[2] =-1;
msg.JointPolarity[3] =-1;
msg.P[0].i16=4000;
msg.P[1].i16=4000;
msg.P[2].i16=4000;
msg.P[3].i16=4000;
msg.I[0].i16=1;
msg.I[1].i16=1;
msg.I[2].i16=1;
msg.I[3].i16=1;
msg.D[0].i16=24;
msg.D[1].i16=24;
msg.D[2].i16=24;
msg.D[3].i16=24;

//msg.change_endian();

while(1)
{
        for(int i =0; i<54; i++)
        {
            writebuf[i]=msg.data[i];

            printf("D: %d,  %d \n", i, msg.data[i]);
        }

        printf("L0: %d, %d, %d", msg.P[0].i16, msg.P[0].data[0], msg.P[0].data[1]);

        int r =jointencoder.xfer1(writebuf, readbuf, 54);
}
我的问题是为什么D:1会出现?我对联合和结构的理解是,因为命令类型是uint8_t,所以它应该只占用一个数据空间,因此上限[0]应该从D:1开始,但似乎命令类型充当uint16_t并发布另一位。为什么会这样


注意:您可能会看到索引上升到计数数据[53],这应该是超出范围的,但我需要读取并发送它,以便能够解构另一端的数据。

几乎可以肯定,在
commandtype
上限之间有一个填充字节;2字节
myint16\t
数据类型在偶数字节边界上对齐

struct {
    uint8_t commandtype;
    myint16_t UpperLimits[4];
    ...
如果您可以打印匿名结构和联合的大小,您可能会发现它至少是54字节(您认为应该是53字节)。作为联合的匿名成员嵌入的未标记结构类型的缺点之一是,无法轻松打印结构的大小。为结构指定一个标记(
struct tag{uint8\u t commandtype;…
),以便打印出其大小


使用当前框架无法轻松解决此问题。

您需要告诉编译器如何对齐并集或结构中的元素。只需在定义之前添加#pragma pack(push,1),指示编译器对齐单字节边界上的相邻元素,然后使用#pragma pack(pop)还原为编译器的默认对齐方式。出于性能原因,您不希望对所有结构/联合/类使用单字节对齐方式,因此最好将联合定义封装在pragma对中

例如:

#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)

assert(sizeof two_bytes == 2);
#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)

assert(sizeof two_bytes == 2);