你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / C专栏
C Primer Plus 02---整数溢出和格式化输出(有趣的数据存储环---可以这么理解)
 
[cpp]  
#include<stdio.h>  
int main(void)  
{  
    int i = 2147483647;  
    unsigned int j = 4294967295;  
      
    printf("%d*%d**%d\n",i,i+1,i+2);  
    printf("%u*%u**%u\n",i,i+1,i+2);  
    printf("%d*%d**%d\n",j,j+1,j+2);  
    printf("%u*%u**%u\n",j,j+1,j+2);  
      
    getchar();  
    return 0;  
}  
运行结果如下
2147483647*-2147483648**-2147483647
2147483647*2147483648**2147483649
-1*0**1
4294967295*0**1
知识点讲解如下:
当一个整数超过他所能表示的最大值以后,就会循环回去继续从开头开始,就像是一个环一样。所以,对于第一个printf和第四个printf不用讲解了吧。
那么对于第二个和第三个printf语句呢?没错,还是涉及到数据的存储管理。可以看我的上一篇帖子,当然有兴趣的可以这么理解。如下
对于第二个,我没什么说的,很明显,u的正数范围比较大,所以,i会一直加一。
对于第三个,因为超出范围了,所以变为-1。至于为什么变为-1,也很简单,
为了帮助大家理解,先举个相同范围输出,正常的例子,比如说范围是0-9,那么我现在数字是10,那么循环一圈过去,相当于是0。实际上,同样的,对于不同的数据类型的输出,也是遵循这种规律的。
针对上面的输出的第三个为什么是-1呢,那你也可以这么想,实际上是4294967295,计算机编译的时候,发现不是%d类型,比较大,那么就循环几圈吧,先循环一圈吧(这里所说的全就是指的是数据可表示的长度范围,对于4294967295,一圈就是4294967296),减小到-1,发现-1在%d的范围内,所以就是-1了,除以的得到的余数,不同意的可以自己去验证,本人已经验证过了。
总之一句话,如果编译运行没错误,那么你就需要按照计算机的思想去理解,他不会出错,因为他也只是程序而已,既然可以运行,那么就肯定有可以运行的规则。上面我说的就是一个规则,当然只是理解而已,实际上,计算机只是取位不同,%d取得是低位16个1(注意,我机子32位系统,int型占32个字节),然后低位中的最高一位0代表正,1代表-,然后计算机内部计算,取得都是补码-1,所以值变成-1喽。(注意,一个是无符号,一个是有符号,补码值按照不同的公式算)(注意,跟我刚才说的,减一圈,实际上减的就是高位的数据,一直到减为0,实际上计算机根本没有减为0,直接就舍去了,但是我们可以这样理解,比较方便)有兴趣的可以看上篇帖子,比较详细。还有这篇帖子http://bbs.csdn.net/topics/340253678还有这篇帖子http://blog.csdn.net/wang6279026/article/details/8114805大部分都是这样的,都看一遍估计就明白了。
再举个例子:
printf函数不管你的变量类型,只管按照格式符的含义来解释数据
例如:
int i=-1;
printf("%u\n",i);
32位平台会输出4294967295,因为-1的源码是32个1(在32平台上)
16位的输出65535
个人理解,欢迎大家批评指正。可能有些地方转不过去,欢迎交流。
2.格式化输出
[cpp]  
#include<stdio.h>  
int main(void)  
{  
    unsigned int un = 3000000000;  
    short end = 200;  
    long big = 65537;  
    long long verybig = 12345678908642;  
      
    printf("%u,%d\n",un,un);  
    printf("%hd,%d\n",end,end);  
    printf("%ld,%hd\n",big,big);  
    printf("%lld,%ld\n",verybig,verybig);  
      
    getchar();  
    return 0;  
}  
 
这个程序也可以按照我的自创的那种方法理解。注意:h代表short(16位),l代表long
输出结果是:
3000000000,-1294967296
200,200
65537,1
12345678908642,1942899938
3.显示八进制和十六进制
[cpp] 
#include<stdio.h>  
int main(void)  
{  
    int x = 100;  
      
    printf("%d*%o**%x\n",x,x,x);  
    printf("%d*%#o**%#x\n",x,x,x);  
      
    getchar();  
    return 0;  
}  
输出结果:
100*144**64
100*0144**0x64
4.好了,那我总结一下精髓吧
无符号与有符号数据都是循环的,但是如果两个类型不匹配输出,实际上是没有问题的,因为,一个计算机内部的二进制数,既可以是有符号数,也可以是无符号数,仅此而已。这才是真正的核心。
最后举个小例子:假设平台是8位的,11111111的无符号数是127,有符号数是-1.他们在计算机内部的二进制是一样的。
  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089