C语言的基本数据类型有三种:
字符型(char)
整型(int)
浮点型(float)
C语言的最早的基本数据类型就是这三。(后面还有C90,C99,C11刚更新的,以后再说)
今天的重点是结合实际来发现C语言基本数据类型的内存溢出问题。
首先,C语言在头文件<limits.h>里面定义了几种数据类型的值范围。
char | int | short | long | long long |
SCHAR_MAX | INT_MAX | SHRT_MAX | LONG_MAX | LLONG_MAX |
SCHAR_MIN | INT_MIN | SHRT_MIN | LONG_MIN | LLONG_MIN |
UCHAR_MAX | UINT_MAX | USHRT_MAX | ULONG_MAX | ULLONG_MAX |
CAHR_MAX | ||||
CHAR_MIN |
在了解内存溢出问题前我们先补充一下计算机基础知识---数字系统。
计算机是从自然界抽象出来的计算工具,所以我们需要将自然界的数据存储到计算机上,它才能进行计算。所以人们就发明了二进制存储方式。(不要问我为什么不用十进制,因为在机器中用电流来表示0和1,频率高的是1,低的是0,真的是为难喔一个渣渣文科生了。而最早的计算机非常庞大,非常耗电,用十进制电流很不稳定。先不说技术问题,当时的电还真的烧不起这十进制的机器。真感兴趣的可以去查资料。)
关于进制,喔默认为你知道了解,并能进行简单运算。
那么怎么把数据存进去呢?
这二我们就得提到这世界上的10种人了,懂二进制和不懂二进制的。
1,原码:就是用二进制直接表示。(也就是unsigend数)
可是问题来了二进制表示那负数怎么表示呢?(比如-1,-2)
对就是将四位0000的最高位用来表示符号(0为正,1为负)
例如:0001(1) + 1001(-1) = 1010(-2) 不成立啊
0000 + 1000 =1000(-0)这完全不符合自然逻辑啊
可是原码表示有符号数时存在一个负零,这是与我们的初衷不负的。怎么办?
2,那就是反码:将有符号数符号位不管,其他位反转(0变1,1变0),正数的反码就是它本身。
例子:0001 + 1110 = 1111 再进行取反运算就成了 1000,结果是对了,可是负零,你不觉得有什么不妥吗?
3,再来,补码就是在反码的基础上加一。(同样正数不进行处理)
(再一次感慨老大的聪明,说计算机不要天赋的,自己多揣摩吧!但是咱们也不能灰心啊)
例子:0001 + 1111 =11110 处理:去掉最高位,加一,取反——————0000就是0啊
好,终于把大象塞进冰箱了。该关门了。
这里我们只讨论整型的溢出问题。
#include <limits.h>
#include <stdio.h>
//整型的内存溢出
int main(void){
printf(" INT_MAX = %d\n",INT_MAX);//INT_MAX = 2147483647
printf(" INT_MIN = %d\n",INT_MIN);//INT_MIN = -2147483648
printf(" INT_MAX + 1 = %d\n",INT_MAX + 1);//INT_MAX + 1 = -2147483648
printf(" INT_MIN-1 = %d\n",INT_MIN-1);//INT_MIN-1 = 2147483647
return 0;
}
看到了吧,INT_MAX + 1 = INT_MIN。
大家可以以时钟来联想这个溢出问题,一下就懂了。
十二点加一,指针不会指向十三点而是一点。
注解:C语言中int是默认的有符号型整数。(为了方便输入嘛)