[牛人杂谈] int型整数在内存中的存储方式

[复制链接]
250|20
 楼主 | 2018-12-19 14:20 | 显示全部楼层 |阅读模式
int类型在内存中的方式
起因:话说楼主在写一个将string类型转化为int类型的函数,就是把atoi()这个函数重写一下,当考虑到溢出这种情况的时候,写下了这样一行代码:
  1. if((!minus&&num>0x7fffffff)||(minus&&num<ffffffff)){
  2.     num=0;
  3.     break;
  4. }
  5. 注:bool minus 是判断该数字是正还是负。
复制代码

等到测试的时候发现输入一个负数的字符串,得到的结果居然是0。
我敏锐的发掘,一定是num=0这句起了作用,但是按说不应该进入这个if语句啊。
于是我开始分析,int类型是带符号的类型,即第一位是符号位,当符号位为0的时候表示正数,当符号位为1的时候表示负数,那我输入的应该没错啊,0xffffffff不应该是十进制数2147483647这个数的负数模式-2147483647么??
楼主不解,于是开始试验。
    int i=0xffffffff;
    cout << i;
输出结果:-1
我就震惊了,明明应该是那么多位的负数,而且这么多个f就给我个-1,我真想问电脑你是怎么想的。后来我看了一下书,书上类似的判断用的是
minus&&num<80000000
于是我有些下了下面的代码
    int i=0x80000000;
    cout << i;
输出结果:-2147483648


 楼主 | 2018-12-19 14:20 | 显示全部楼层
好吧,看来书上是对的,也不知道电脑是怎么想的怎么翻译的?
于是我开始认真思考这个问题,电脑是怎么想的,发明c++语言的人是怎么想的,以及为什么?
上学的时候隐约记得好像和加法还有减法有关。
于是拿出纸笔,开始模拟。
首先我把int 1和int -1相加,即0x0000001+0xffffffff,诶,奇迹来了,结果是0x100000000,大家看好是9个16进制位哦,而按照int型的存储空间应该是8个16进制位,即4个字节,于是
就剩下0x00000000,这不正好是0么!于是楼主虎躯一震,继续试验。
如果是int 1减去int -1呢?
即0x00000001-0xffffffff这咋减?于是楼主联想上面的例子,决定在整数前面补1位,即0x100000001-0xffffffff得到的结果正好是0x00000002。于是我服了,人家发明的人想的果然就比我们多啊,你想啊,如果是这样就不用进行符号转化了啊,否则,如果按照我之前的理解,-1是0x80000001的话,1+(-1)就应该是先把-1转化为+1,再做加法即0x00000001+0x00000001=0x00000002,这样的话处理起来太麻烦了,而且遇到正数和负数的处理过程不一样大大影响效率。

好了上面的分析分析完了,接下来我说说其他的拓展心得。
1.如果你看见了一个类似0xfffffffa怎么判断它是负几呢?很简单,用0x100000000-0xfffffffa得出来的数加个负号就是了。
2.如果想将一个int型整数取反直接使用符号“~”然后再+1即可,这个方法在效率上比使用符号块,因为是位操作,比运算符操作要快。
如:a=~a+1
| 2018-12-19 17:24 | 显示全部楼层
不同变量类型定义数的方式不同,比如最高位是0还是1的问题。
| 2018-12-20 15:13 | 显示全部楼层
能否用这种方法判断大小端?
| 2018-12-20 21:49 | 显示全部楼层
研究研究这个,对C语言学习还是很有帮助的。
| 2018-12-20 23:06 | 显示全部楼层
PC里和单片机里好像还是不同的,不同厂家的单片机貌似设计的也不同。
| 2018-12-20 23:06 | 显示全部楼层
不知道GCC和KEIL,IAR是不是也有这个区别。
| 2018-12-21 23:38 | 显示全部楼层
以前学习时候,学过这个,后来工作用的时候,发现没用过。
| 2018-12-21 23:49 | 显示全部楼层
小数的存储我一直不懂
| 2018-12-22 00:04 | 显示全部楼层
睡觉了,明天试试。
| 2018-12-23 00:33 | 显示全部楼层
貌似可以用指针观察一下怎么存的。
| 2018-12-23 00:39 | 显示全部楼层
大年纪的Bool值都是假的吧。
| 2019-1-7 13:13 | 显示全部楼层
这样做不对啊  应该是无符号数
| 2019-1-8 11:27 | 显示全部楼层
定义为无符号类型
| 2019-1-8 14:37 | 显示全部楼层
数据格式要用对。
| 2019-1-8 14:37 | 显示全部楼层
选择变量类型很重要。
| 2019-1-9 09:38 | 显示全部楼层
C语言的数据类型要求很严格的。
| 2019-1-11 09:19 | 显示全部楼层
本帖最后由 whtwhtw 于 2019-1-11 09:27 编辑

计算机用的是补码模式,正数的补码和源码一样,负数是补码模式!!!,负数表现格式为符号位1;后面数为反码+1。
| 2019-1-11 09:34 | 显示全部楼层
0XFFFFFFFF的二进制是1111 1111 1111 1111 1111 1111 1111 1111,表示为32位有符号数据就是(-)[111 1111 1111 1111 1111 1111 1111 1111],中括号中是补码+1的结果,我们先-1得[111 1111 1111 1111 1111 1111 1111 1110],这是反码,我们再求反得[000 0000 0000 0000 0000 0000 0000 0001]。所以实际表示的数据就是-1。
| 2019-1-11 09:40 | 显示全部楼层
计算机中是分+0和-0的,并规定他们相等,所以有符号的0x00000000和0x80000000是相等的
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

快速回复 返回顶部 返回列表