union pw {int i;char ch[2]; }a; main () {a.ch[0]=10; a.ch[1]

问题描述:

union pw {int i;char ch[2]; }a; main () {a.ch[0]=10; a.ch[1]=0; printf ("%d\n",a.i); } 为什么不是0
1个回答 分类:综合 2014-10-31

问题解答:

我来补答
要想弄清这个问题 必须要 弄清楚 什么是联合?
联合是一种可构造的数据类型,就像定义的那样
{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 经过测试
再问: 感觉上面的东西有点复杂化了。我也编过这个程序,结果是10,不是0.。你再来看看这个 main() { union { char a; int i; }t; t.a='A';t.i=1; printf("%d%d",t.a,t.i); } 结果是11.。这个感觉是有覆盖了,为什么第一个就不体现覆盖呢?
再答: 你仔细 看上面的东西吧,,看懂了 你再遇到 这类问题 就明白了。。看不懂 就天天看,或问问别人 问问老师, 答案一出,就被选为 标准答案了, 可见管理员 都看过了 ,你要 弄懂上面的,,其它的都不在话下了
 
 
展开全文阅读
剩余:2000