此文探究一下不同类型数据(int,short,char,float...)在计算机中的存储情况。
1.整形数据在内存中的存储
c语言中的整形数据分别有:char(1字节),short(2字节),int(4字节),long(8字节)。
对于整形数据来说,计算机存储的是其补码。
例:
int a=1;
int b=-1;
对于正数来说,其原码与补码相同,对于负数来说,其补码等于源码的反码加1。
a:
原码:00000000 00000000 00000000 00000001
补码: 00000000 00000000 00000000 00000001
b:
原码:10000000 00000000 00000000 00000001
反码: 11111111 11111111 11111111 11111110
补码: 11111111 11111111 11111111 11111111
大小端:
在计算机中,每个地址单元对应着一个字节,而地址单元本身在内存中也有数值高低之分,分为高地址和低地址。由于有些整形数据的大小超过了一个字节,因此就需要占据多个地址位。,由此产生了大端存储和小端存储。
例:
a在计算机中的补码为:
00000000 00000000 00000000 00000001
共占据四个字节
大端存储:数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中
小端存储:指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中
2.整形数据在内存中的存储和输出实例
1.
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
求分别输出什么
一.分析三个数据放在内存中的实际情况
三个数据在内存中的实际存储值分别为:
char a: 11111111
signed char b:11111111
unsigned char c:11111111
原因:由于-1是个整型值,因此其补码为:11111111 11111111 11111111 11111111
若要将其放在只有1个字节的char变量中,需要截取低地址的一个字节的数据(小端存储情况)
二.分析输出情况
三个输出值皆为%d,即整形输出。
对于a来说,a属于有符号数,输出时需要进行整型提升,在高位补符号位。提升之后的数据为:
11111111 11111111 11111111 11111111
此时输出值为-1
对于b来说,b属于有符号数,输出时需要进行整型提升,在高位补符号位。提升之后的数据为:
11111111 11111111 11111111 11111111
此时输出值为-1
对于c来说,c属于无符号数,因此输出时需要进行整型提升,在高位补0。提升之后的数据为:
00000000 00000000 00000000 11111111
此时输出值为255
2.
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
一.分析数据放在内存中的实际情况
-128的原码为:10000000 00000000 00000000 10000000
-128的补码为:11111111 11111111 11111111 10000000
放在a中的数据:10000000(小端存储)
二.分析输出情况
对于a来说,a属于有符号数,输出时需要进行整型提升,在高位补符号位。提升之后的数据为:
11111111 11111111 11111111 10000000
由于需要输出一个无符号数,则需要将上述符号位看作有效符号位输出,即输出数值为11111111 11111111 11111111 10000000的二进制正整数。
输出结果:4294967168
3.
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
一.分析数据放在内存中的实际情况
128的补码为:00000000 00000000 00000000 10000000
放在a中的数据:10000000(小端存储)
二.分析输出情况
对于a来说,a属于有符号数,输出时需要进行整型提升,在高位补符号位。提升之后的数据为:
11111111 11111111 11111111 10000000
由于需要输出一个无符号数,则需要将上述符号位看作有效符号位输出,即输出数值为11111111 11111111 11111111 10000000的二进制正整数。
输出结果:4294967168
4.
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
一.分析数据放在内存中的实际情况
-20原码:10000000 00000000 00000000 00010100
-20反码:11111111 11111111 11111111 11101011
-20补码:11111111 11111111 11111111 11101100
j中存放:00000000 00000000 00000000 00001010
i+j=11111111 11111111 11111111 11110110
二.分析输出情况
由于%d可输出有符号整型,所以输出结果为:
-10
5.
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
i作为一个无符号整型变量,在内存中没有符号位,所有的数字都为有效数字
程序进行第一次:
i: 00000000 00000000 00000000 00001001
程序进行第二次:
i: 00000000 00000000 00000000 00001000
...
程序进行第十次:
i: 00000000 00000000 00000000 00000000
当程序进行第十一次时,i-1的实质是:
00000000 00000000 00000000 00000000+11111111 11111111 11111111 11111111
=11111111 11111111 11111111 11111111
由于输出是无符号数的格式,因此输出值为:
4294967295
由于i是是无符号数,此程序将死循环下去。