整型数据在内存中的存储,是一个值得细细体会的问题,千万不要把它忽视了!!!下面我们来详细谈一谈:
什么是整形?
整形有:char short int long long long
各种整形又分为:signed (有符号型,没有写 signed 这个关键字的类型默认是有符号类型:例如上一行的类型都是有符号类型)
unsigned(无符号类型)
各种类型的范围:
认识类型范围前先看看两个密诀:1000 0000 1后面7个0,则表示:2的7 次方 即128
0111 1111 0后面7个1,则表示:2的7次方减1 即128-1=127
同时请记住边缘数据:2^7 = 128 2^15 = 32768 2^31 = 2147483648
2^8 = 256 2^16 = 65536 2^32 = 4294967296
2^10 = 1024
好,现在我们来看看具体类型的范围,注意:下面带括号意思是书写的时候可以省略,系统会自动默认有
(signed) char (有符号char整形, 32位机器占一个字节8bit位)
最小值 1000 0000 [2^7](-128) 每个类型的这种形式都是有符号数的最小值
最大值 0111 1111 [2^7-1] (127) 此时最大值要是再加一,结果就是-128
unsigned char (无符号char整形, 32机器占一个字节8bit位)
最小值 0000 0000 (0)
最大值 1111 1111 [2^8-1] (255) 此时最大值要是再加一,结果就是0
(signed) short (有符号短整形, 32位机器占两个字节16bit位)
最小值 1000 0000 0000 0000 [2^15](-32768) 每个类型的这种形式都是有符号数的最小值
最大值 0111 1111 1111 1111 [2^15-1] (32767) 此时最大值要是再加一,结果就是-32768
unsigned short (无符号短整形, 32机器占两个字节16bit位)
最小值 0000 0000 0000 0000(0)
最大值 1111 1111 1111 1111 [2^16-1] (65535) 此时最大值要是再加一,结果就是0
(signed) int (有符号整形, 32位机器占四个字节32bit位)
最小值 1000 0000 0000 0000 0000 0000 0000 0000 [2^31](- 2147483648) 每个类型的这种形式都是有符号数的最小值
最大值 0111 1111 1111 1111 1111 1111 1111 1111 [2^31-1] (2147483647) 此时最大值要是再加一,结果就
是-2147483648
unsigned int (无符号整形, 32机器占四个字节32bit位)
最小值 0000 0000 0000 0000 0000 0000 0000 0000(0)
最大值 1111 1111 1111 1111 1111 1111 1111 1111 [2^32-1] (4294967296) 此时最大值要是再加一,结果就是0
此时附加一个内容,数据在内存中的存储是大端还是小端?
小端:数据的低位 存放在内存的低地址 称为小端存储方式 :简称小(低位)小(低地址)小(小端)
大端:数据的高位 存放在内存的高地址 称为大端存储方式
上一张图来解释清楚:
看一下具体内存的存储方式(下图是小端存储)
现在让我们来看看关于大小端的笔试题:
//方法一
#include <stdio.h>
#include <windows.h>
int check_sys()
{
int i = 1; //内存中 :00 00 00 01 或 01 00 00 00
return (*(char *)&i);//int型数据地址类型是 int * ,所以现在要强转成char * ,
//因为解引用时我们要按照 char 类型读取1个字节。
}
int main()
{
int ret = check_sys();//直接用一个函数判断
if (ret == 1)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
system("pause");
return 0;
}
//方法二(利用联合体enum)
#include <stdio.h>
#include <windows.h>
int check_sys()
{
union
{
int i;
char c;
}un;//声明并定义
un.i = 1;
return un.c;
}
int main()
{
int ret = check_sys();//直接用一个函数判断
if (ret == 1)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
system("pause");
return 0;
}
现在我们来总结一下三个结论!!!重要结论!!!
1 往内存中存数据时,直接按照类型大小把数据的 "补码" 存进内存。(正数原码==反码==补码,负数原码取反加1 == 补码)
2 CPU去内存取数据时,遇到整形提升时,看原来数据的类型:有符号数则全部添加符号位,无符号数全加 0
3 打印的时候,输出到屏幕上时,%d 是输出有符号数十进制, 看CPU符号位,正数直接打印,负数符号位不变,其余 位减1再取反
%u 是输出无符号数十进制 CPU符号位是0 直接打印
下面我们进入实战演练环节:
1
#include <stdio.h>
#include <windows.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a = %d b = %d c = %d\n", a, b, c);
system("pause");
return 0;
}
我们来分析一下: