先来看一个奇怪的问题
#include<stdio.h>
union test
{
int k;
char c[2];
}a;
int main()
{
a.k=-7;
printf("%d,%d",a.c[0],a.c[1]);
}
再说一下存储编码
- C 语言在内存中存储数据是使用补码
现在再猜猜看之前程序的输出结果是什么?
我们来先自己算一算
int 在内存中占 4 个字节
-7的源码也就是 10000000 00000000 00000000 00000111
那么补码就是符号位不变,其余按位取反+1
- 即-7 在内存中为: 11111111 11111111 11111111 1111111001
现在再看看结果
weijia$ gcc uniontest.c
weijia$ ./a.out
-7,-1
为什么是-7 和-1,而不是 -1 和 -1 呢?
其实在内存中(vs和gcc实测)存储是:低位在前,高位在后
内存如下
地址 | ||||||||
---|---|---|---|---|---|---|---|---|
0x00: | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
0x01: | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
0x02: | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
0x03: | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
读取的时候地址为:
0x03 0x02 0x01 0x00
这就应该明白为什么结果是 -7 和 -1 了吧
再来看一个例子验证一下
#include<stdio.h>
int main()
{
int a=-7;
char *c=(char*)&a;
printf("%d,%d,%d,%d ",c[0],c[1],c[2],c[3]);
return 0;
}
weijia$ gcc inttest.c
weijia$ ./a.out
-7,-1,-1,-1
这样结果是不是就对了,我们将其中的a=-7换成 a=257 试试
因为 257 = 2^8+1
也就是往上一个字节进位,当前字节变成了1
再来看看结果
1,1,0,0
现在的结果是不是跟自己想的一样了?