Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.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_Unions - Fatal编程技术网

C 联合和结构初始化

C 联合和结构初始化,c,unions,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.

我偶然发现了一个基于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);  
我只是不明白为什么输出是
2680
。这些值是如何初始化的? 工会在这里是如何运作的?输出不应该是
12 1
。如果有人能详细解释这里到底发生了什么,那就太好了


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

它可能将{12,1}分配给s.ax中的前2个字符


因此,在32位整数中,它是1*256+12=268

代码并没有按照您的想法执行。大括号初始化第一个联合成员,即
u.s
。但是,由于
u.s
包含两个数组,现在初始值设定项不完整且缺少大括号。它应该是这样的:
u={{{{'a',b'},{'c',d'}}

您应该始终在编译时使用所有警告,一个体面的编译器应该告诉您出了什么问题。例如,GCC说,
初始化器周围缺少大括号(接近“u.s”的初始化)
缺少初始化器(接近“u.s.ab”的初始化)
。非常有用


在C99中,您可以利用命名成员初始化来初始化第二个联合成员:
u={.st={12,1}(这在C++中是不可能的,顺便说一下)第一种情况的对应语法是“代码> u={ s= {{‘a’,‘b’},{'c',‘d’}};<代码>,可以说是更明确和可读

您的代码使用工会的默认初始值设定项,它是工会的第一个成员。12和1都进入ax的字符,因此您看到的结果(这在很大程度上依赖于编译器)

如果要通过第二个memmber(
st
)进行初始化,可以使用指定的初始值设定项:

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

联合体的大小是组成联合体的最大元素的最大大小。因此在本例中,您的联合类型在32位平台上的大小为8字节,其中
int
类型各为4字节。但是,联合的第一个成员
s
只占用2个字节,因此与
st.a
成员的前2个字节重叠。由于您使用的是小端系统,这意味着我们将重叠
st.a
的两个低阶字节。因此,当您使用值
{12,1}
初始化联合时,您只初始化了
st.a
的两个低阶字节中的值。。。这将使
st.b
的值初始化为
0
。因此,当您试图打印出包含两个
int
而不是
char
联合成员的结构时,您将得到
128
0
的结果,代码将
u.s.ax[0]
设置为12和
u.s.ax[1]
设置为1
u.s.ax
被叠加在
u.st.a
上,因此
u.st.a
的最低有效字节被设置为12,最高有效字节被设置为1(因此您必须在小端结构上运行),给出0x010C或268的值。

实际上您需要两组额外的大括号(一个用于联合,一个用于结构,一个用于数组):
u={{{{'a',b'},{'c',d'}}
@KerrekSB谢谢。这可能是最好的答案。您能否解释一下,既然初始化问题已经解决,为什么输出是
2680
。@NiteeshMehra:256+12…加上一大把luck@KerrekSB谢谢,我想我明白了,如果我错了,请纠正我:位的设置如下
00000001 00001100
=256+8+4=268.对吗?那为什么u.st.b=0呢?@NiteeshMehra:事情是这样的。s.ax[2]和s.ab[2]按小尾端顺序压缩成4个字节。您的初始化将s.ax[0]初始化为12(0x0C),将s.ax[1]初始化为1(0x01)。其他所有内容都初始化为0。(我不知道这是否是“规范”)假设您使用的是32位整数,结果的数据布局如下(左边的最低字节):0C 01 00 00 00所以当你打印第一个4字节的int时,你得到了0x000001c,或268,当你打印第二个4字节的int时,你得到了0x00000000,神秘的0。初始化器怎么知道你想初始化
st
,而不是
s
?如果我知道,这个问题就不会在这里了。为什么
0x010C
?那不应该是
0x001C
?谢谢,我想我明白了,如果我错了请纠正我:位的设置如下
00000001 00001100
=256+8+4=268。对吗?但是为什么u.st.b=0?是的-
00000001
00001100
0x010C
。u.st.b是零,因为只提供了两个值,而这些值都是零分配给
u.s.ax[0]
u.s.ax[1]
。这两个字符覆盖
u.st.a
的最低有效端,将上半部分和
u.st.b
默认设置为零。输出是
268
0
。为什么联合
s
的第一个成员占用2个字节?不应该占用4个字节吗?它有2个大小为2的字符数组。因此应该是这样2*2=4.如果我错了,请纠正我。