简体   繁体   English

联盟成员数据对齐

[英]Union member data alignment

I'm having some problem with data alignment in a union, which I can't seem to figure out. 我在联合中遇到数据对齐问题,我似乎无法弄清楚。 Using a union similar to the one below, there seems to be some data offset at the union's base address. 使用类似于下面的联合,联盟的基地址似乎有一些数据偏移。

typedef union MyUnion
{
    struct MyStruct
    {
        uint16_t val_1;
        uint8_t  val_2;
        uint8_t  val_3;
    }data;
    uint8_t data_array[4];
}MyUnion;

At some point I've filled the struct in with data, 在某些时候,我已经用数据填充了结构,

my_union.data.val_1 = 65535;
my_union.data.val_2 = 0;
my_union.data.val_3 = 0;

I then try to access the data using the array. 然后我尝试使用数组访问数据。 What I expect to see at the base address of the array is the first byte of val_1, 255. However, when accessing the data in the array, it seems to be offset from the struct's base by 1 byte. 我期望在数组的基地址看到的是val_1的第一个字节,255。但是,当访问数组中的数据时,它似乎从结构的基数偏移了1个字节。

printf("Bytes of struct: %#08x\n", my_union.data.val_1);
printf("Bytes of array:  %#08x\n", my_array.data_array[0]);

No matter what values I put in the above results in output similar to this. 无论我在上面的结果中输入什么值,输出都与此类似。

Bytes of struct:  0x00ffff
Bytes of array:   0x0000ff

I first thought that the members may be offset somehow and were referencing different memory address's, but when I print their addresses, they are the same. 我首先想到的是成员可能会以某种方式偏移并引用不同的内存地址,但是当我打印它们的地址时,它们是相同的。

Also, if I print the following values they are equal. 此外,如果我打印以下值,它们是相等的。

printf("Bytes of struct: %#08x\n", my_union.data);
printf("Bytes of array:  %#08x\n", *(my_array.data_array - 1) );

Output: 输出:

    Bytes of struct:  0x00ffff
    Bytes of array:   0x00ffff

I'm sure I'm missing something simple, but I can't figure it out, at the moment. 我确定我错过了一些简单的东西,但此刻我无法弄明白。 Thank you for any help in advance. 感谢您提前提供的任何帮助。

Run on a little-endian machine (Intel Core i7, Mac OS X 10.9.1 Mavericks, GCC 4.8.2), the following program: 在小端机器(Intel Core i7,Mac OS X 10.9.1 Mavericks,GCC 4.8.2)上运行,以下程序:

#include <inttypes.h>
#include <stdio.h>

typedef union MyUnion
{
    struct MyStruct
    {
        uint16_t val_1;
        uint8_t  val_2;
        uint8_t  val_3;
    } data;
    uint8_t data_array[4];  // NB: was unint8_t!!!
} MyUnion;

int main(void)
{
    MyUnion my_union;

    my_union.data.val_1 = 0xFEDC;
    my_union.data.val_2 = 0xBA;
    my_union.data.val_3 = 0x98;

    printf("val_1 = 0x%.4" PRIX16 "; val_2 = 0x%.2" PRIX8 "; val_3 = 0x%.2" PRIX8 "\n",
           my_union.data.val_1, my_union.data.val_2, my_union.data.val_3);

    char const *pad = "";
    for (size_t i = 0; i < sizeof(my_union.data_array); i++)
    {
        printf("%sarray[%zu] = 0x%.2" PRIX8, pad, i, my_union.data_array[i]);
        pad = "; ";
    }
    putchar('\n');

    return 0;
}

produces the output shown: 产生显示的输出:

val_1 = 0xFEDC; val_2 = 0xBA; val_3 = 0x98
array[0] = 0xDC; array[1] = 0xFE; array[2] = 0xBA; array[3] = 0x98

This is very much what I'd expect. 这是我所期待的。 You'd get different output on a big-endian machine (anything but Intel, more or less). 你会在大端机器上获得不同的输出(除英特尔以外的任何东西,或多或少)。

You need to adapt this code (or something very similar) to demonstrate whatever problem you perceive you have, and show the modified code and the actual output and your explanation of what you expect and why you expect the different output. 您需要调整此代码(或非常类似的代码)来演示您认为自己遇到的任何问题,并显示修改后的代码和实际输出以及您对期望内容的解释以及您对不同输出的期望。

This is definitively wrong: 这是明确错误的:

printf("Bytes of array:  %#08x\n", my_array.data_array);

you are printing the address of the first element of the array, instead of the contents, which is what seems to interest you. 您正在打印数组的第一个元素的地址,而不是内容,这是您感兴趣的内容。

Printing a pointer should use the %p format, anyhow, so a decent compiler should give you a warning. 无论如何,打印指针应该使用%p格式,所以一个体面的编译器应该给你一个警告。

To print the contents of the array, you'd have to print each element of it. 要打印数组的内容,您必须打印它的每个元素。 The correct format specifier for uint8_t (not unint8_t !) is the macro PRIx8 . uint8_t (不是unint8_t !)的正确格式说明符是宏PRIx8

try this 尝试这个

printf("Bytes of struct: %#08x\n", *(uint32_t*)&my_union.data);
printf("Bytes of array:  %#08x\n", *(uint32_t*)my_union.data_array);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM