static int i = 2;
union U {
int a, b;
char c[3];
}u;
int main(){
u.b = 0x6;
for(;i; u.b++)
u.b = u.a << i--;
printf("%d %o %s", u.a, u.b, u.c);
return 0;
}
这段代码给出了字符数组的输出为3.现在我知道这段代码特别是当我存储到一个变量并访问其他一些变量时,会产生几个Undefined Behaviour
,但仅仅是为了实验的目的,任何人都可以向我解释为什么u.c
的值为3
。
注意:内部存储器结构更好理解
答案 0 :(得分:1)
在for循环之后,union u
包含位:
0x00000033
分成字符的是
0x33 0x00 0x00
所以
c[0]=0x33
c[1]=0x00
c[2]=0x00
和0x33恰好是数字'3'的ASCII代码;
答案 1 :(得分:0)
你可以巧妙地测试它打印a的十六进制代码:
printf("\n%X\n", u.a);
输出为0x33
,即ASCII 3
for循环
b=0x06
2
=&gt; b=0x18
b
1
=&gt; b=0x32
b
=&gt; b= 0x33
您定义一个联合,然后与b
重合。
a
和[{1}}的前3个字节也可由b
访问。
BTW printf输出取决于数据的字节顺序。
在您的情况下, Little Endian ,c
打印ASCII 3,因为printf
是:
c
如果 Big Endian c[0]=0x33
c[1]=0x00
c[2]=0x00
没有打印任何内容,因为printf
是:
c
答案 2 :(得分:0)
u.a,u.b和c的字节都占用相同的内存。既然你自己和u.b具有相同的类型,它们本质上是相同的变量。循环
int i=2;
u.b = 6;
for(;i; u.b++)
u.b = u.a << i--;
可以写成(仅为了清晰起见,使用u.b):
u.b = 6;
u.b = u.b << 2; // u.b is now 24 (one bit shift left is multiplying by 2)
u.b++; // u.b is now 25
u.b = u.b << 1; // u.b is now 50
u.b++; // u.b is now 51.
现在,首先是低字节的PC上的32位整数的内存布局是字节方式,51-00-00-00。
将这些字节解释为字符串,就像你告诉printf进行%s
转换一样,意味着51被视为ascii值,表示字母 3 。幸运的是,下一个字节确实是0,因为整数很小,所以字符串终止。 printf将打印 3 。