union pw {int i;char ch[2]; }a; main () {a.ch[0]=10; a.ch[1]=0; printf ("%d尀n",a.i); } 为什么不是0

2024-11-25 04:25:13
推荐回答(4个)
回答1:

要想弄清这个问题 必须要 弄清楚 什么是联合?

联合是一种可构造的数据类型,就像定义的那样
{int i;char ch[2];} 首先,你要弄清楚他占多大内存,就像 INT 占四字节,SHORT 占两字节,
它占多大呢? 测试一下 发现结果 是 4字节, 也就是它用这 四个字节 来存储 其对应的值,我们想,你一个 INT 就要占四字节 ,那CH 数组的数据放在哪里呢? 其实 这就是联合的特性,他不管那么多,他只负责对内存里的值进行 读写, 比如 这四字节的数据 是 10 05 6A 01 ,当 你用a.i 的时候 ,它的值 是 016A0510 这个补码对应的 整数值,当你用 ch时,它 的值是 10 05 这两个值,当你 修改 a.ch[1]=65; 那这四字节 产生变化 ,10 65 6A 01,这个时候 再输出 a.i 其值就发生了变化,就变成了 016A6510 这个补码对应的值, 如果 你将 a.i=1,则这四个字节的数据变成 01 00 00 00,同理,你访问 a.ch[0] 得到的是 01,a.ch[1] 得到的 00。

所以你上面 的例子 是怎么回事呢?
首先a.ch[0]=10,其值 变为 0A CC CC CC 。注意没有初始化的值 为CC
然后a.ch[1]=0,其值变为 0A 00 CC CC,然后你输出,a.i 其值 应该是 CC CC 00 0A 这个补码对应的 整数值,
CCCC000A的 二进制:用计算器求 :11001100110011000000000000001010
要想求其真值 ,先减一,再取反吧,,首先判断 这个数是负数,因为第一位为 1
减一后 其值:11001100110011000000000000001001
各位取反: 00110011001100111111111111110110
将上面的数 拿到计算器 里转换成 10进制,得859045878 ,又因它是 负数,所以最终结果 :
-859045878。 不知道 对不对。。我没进行测试。

上面有点小问题,,由于你 的a 是全局的,,数据被初始化为 00 00 00 00 而非 CC CC CC CC
所以上面的计算 有点小问题,,如果 你将其改成 如下 格式 :

#include
union pw
{
int i;
char ch[2];
};
void main ()
{
pw a;
a.ch[0]=10;
a.ch[1]=0;
printf ("%d\n",a.i);
}

则上面的解释 正常通过。 VC6.0 经过测试

回答2:

我研究了一下,认为是这样的:int占两个字节(有些程序上是四个),char占一个字节,但是是有两个元素的数组,所以总共占了两个字节。a.ch[0]为10,即1010,而a.ch[1]是0,即0000。因此最后存储为0000 1010(这里是重点,a.ch[0]在后面),因此答案是10。

回答3:

因为变量i和ch[2]共享同一段内存空间

回答4:

a.ch[0]和 a.ch[1]占两个内存区域,i 的值为a.ch[0]。