C 联合的内存分配
在下面的代码中C 联合的内存分配,c,unions,C,Unions,在下面的代码中 #include <stdio.h> int main() { union a { int i; char ch[2]; }; union a u; int b; u.ch[0] = 3; u.ch[1] = 2; printf("%d,%d,%d\n", u.ch[0], u.ch[1], u.i); return 0; } 有人能解释一下为什么i的值是515吗?联合
#include <stdio.h>
int main() {
union a {
int i;
char ch[2];
};
union a u;
int b;
u.ch[0] = 3;
u.ch[1] = 2;
printf("%d,%d,%d\n", u.ch[0], u.ch[1], u.i);
return 0;
}
有人能解释一下为什么i的值是515吗?联合变量'u'的大小是4字节32位机器。 假设联合变量“u”的起始地址为2000 现在,3存储在2000 ch[0]中,2存储在2001 ch[1]中。 内存位置2000的十进制二进制3值为00000011,而内存位置2001的十进制二进制2值为00000010 现在,当您尝试打印“u.i”时,两个字符变量“ch[0]”和“ch[1]”的值组合在一起,形成一个16位的整数,二进制515的值为000000100000011(十进制)。这就是为什么整型变量'u.i'的值为515。您的机器遵循little endian格式对内存中的字节进行排序。如果你的机器是big-endian机器,那么你可能会得到“u.i”的答案是770而不是515
union a {
int i;
char ch[2];
};
union a u; /* initially it contains gargage data */
工会的所有成员都有共同的记忆。在上述情况下,总共为u分配了4个字节,因为在所需的4字节最大内存中,您可以同时存储i和ch
当语句u.ch[0]=3时;仅执行初始化的ch[0]
ch[1] ch[0]
--------------------------------------
| G | G | G | 0000 0011 | => G means garbage/junk data, because u didn't initialized
--------------------------------------
u
MSB LSB
当u.ch[1]=2时;执行后1个字节初始化为
ch[1] ch[0]
------------------------------------------
| G | G | 0000 0010 | 0000 0011 | => G means garbage/junk data, because u didn't initialized
------------------------------------------
u
MSB LSB
如上所示,在4个字节中,只有前2个字节已初始化,其余2个字节未初始化,因此在打印u.i时,其未定义的行为
若您想要预期的结果,那个么先初始化union变量,然后将其作为
union a u = { 0 }; /* all 4 bytes got initialized at first instance itself, no chance of any junk data */
u.ch[0] = 3;
u.ch[1] = 2;
现在,当你打印u.i时,它会打印整个4字节的数据,即512+3=515,如果是小埃尼迪亚处理器2*256+3=515,你在一台小埃尼迪亚机器上工作,你幸运吗?除非sizeofint==2,否则您也可能会得到垃圾。因为行为未定义。如果您不分配给i,为什么要尝试打印它?此外,联合成员应该一次使用一个。@machine_1,这在C99之后不是很清楚:如果用于读取联合对象内容的成员与上次用于在对象中存储值的成员不同,价值的对象表示的适当部分被重新解释为新类型的对象表示,如6.2.6所述,这一过程有时被称为“类型双关”。这可能是一个陷阱表示。正如@JonathanLeffler猜测的那样,我的机器打印了3,2666567171,但在使用union a u={0}初始化union之后;它给出了正确的32515。为什么会发生特定的操作512+3=515?@Rajsi不是特定的操作,而是对您看到的值的解释。处理器同时读取所有4个字节的u.i。类似地,十进制数字23表示2^10+3^1。您使用的是哪种编译器?如果int为2字节&当printf%d\n时,u.i;执行后,它将尝试打印2个字节的值,从LSB计算到MSB。如果int为4字节,且联合变量u未初始化,则如果联合未初始化为所有0,则其UBIt仅为UB。除符号外,a*256^3+b*256^2+c*256^1+d*256^0同样适用。关于部分初始化和未定义的行为,这一点很好,但是,用递减的地址显示内存内容是完全令人困惑的,而且在小端和大端的讨论中不需要。在你的答案中添加一些格式将有助于使它更清晰,更容易理解。@AfroThundr这是我的第一个答案。我一定会努力提高。感谢您指出这一点。由于联合变量'u'的大小是2字节32位机器,我希望给定成员int I;,u的大小是4字节32位;。我在那里犯了一个错误。它将消耗4个字节。感谢您指出。由于多种原因,行为未定义,u.i未正确初始化。
ch[1] ch[0]
------------------------------------------
| G | G | 0000 0010 | 0000 0011 | => G means garbage/junk data, because u didn't initialized
------------------------------------------
u
MSB LSB
union a u = { 0 }; /* all 4 bytes got initialized at first instance itself, no chance of any junk data */
u.ch[0] = 3;
u.ch[1] = 2;