联合和结构初始化

h4c*_*k3d 13 c unions

我偶然发现了基于C中的工会的代码.这是代码:

    union    {  
        struct  {  
            char ax[2];  
            char ab[2];  
        } s;  
        struct  {  
            int a;  
            int b;  
        } st;  
    } u ={12, 1}; 

    printf("%d %d", u.st.a, u.st.b);  
Run Code Online (Sandbox Code Playgroud)

我只是不明白输出是怎么来的268 0.这些值是如何初始化的?工会如何运作?输出不应该是12 1.如果有人能够详细解释这里到底发生了什么,那就太好了.

我在Windows 7上使用32位处理器.

Ker*_* SB 17

代码不符合您的想法.Brace-initializes初始化第一个 union成员,即u.s.但是,现在初始化程序不完整并且缺少大括号,因为它u.s包含两个数组.应该是一些想法:u = { { {'a', 'b'}, { 'c', 'd' } } };

你应该总是编译所有警告,一个体面的编译器应该告诉你有些不对劲.例如,GCC说,missing braces around initialiser (near initialisation for ‘u.s’)missing initialiser (near initialisation for ‘u.s.ab’).很有帮助.

在C99中,您可以利用命名成员初始化来初始化第二个union成员:( u = { .st = {12, 1} };顺便说一句,这在C++中是不可能的.)第一种情况的相应语法是`u = { .s = { {'a', 'b'}, { 'c', 'd' } } };,可以说更明确和可读!

  • @NiteeshMehra:发生了什么事.s.ax [2]和s.ab [2]以little-endian顺序打包成4个字节.您的初始化将s.ax [0]初始化为12(0x0C)并将s.ax [1]初始化为1(0x01).其他所有内容都被初始化为0.(我不知道这是否是"规范"行为,但这是我期望发生的事情.)假设您使用的是32位整数,结果数据布局如下(左边的最低字节):0C 01 00 00 00 00 00 00所以当你打印第一个4字节的int时,你得到的是0x0000010C,或者268,当你打印第二个4字节的int时,你得到的是0x00000000,神秘的0 . (3认同)
  • 实际上你需要*两个额外的大括号(一个用于联合,一个用于结构,一个用于数组):`u = {{{'a','b'},{'c','d "}}}`. (2认同)

das*_*ght 6

您的代码使用联合的默认初始值设定项,这是其第一个成员。12 和 1 都进入 ax 的字符,因此您看到的结果(非常依赖于编译器)。

如果您想通过第二个成员 ( st)进行初始化,您将使用指定的初始化程序:

union {  
    struct {  
        char ax[2];  
        char ab[2];  
    } s;  
    struct {  
        int a;  
        int b;  
    } st;  
} u ={ .st = {12, 1}}; 
Run Code Online (Sandbox Code Playgroud)


Bor*_*din 5

代码设置u.s.ax[0]为 12 和u.s.ax[1]1.u.s.ax被覆盖,u.st.a因此最低有效字节u.st.a设置为 12,最高有效字节设置为 1(因此您必须在小端架构上运行)给出值 0x010C 或268.