关于ZM问到C中int数据范围溢出

来源:互联网 发布:数据库安全防范 编辑:程序博客网 时间:2024/06/05 11:44
  1. (从原来的博客贴过来的)


    #include<stdio.h>

    int main()

    {

    unsigned int a=377,b=121;//此处为无符号整型,

    printf("%c %c\n",a,b);

    return 0;

    }


这段代码意在用ascll进行代号和字符的转换,sacll码中十进制的121代表字符‘y’


该代码执行后输出一个很有意思的结果



然后把代码里面的int 改成 signed int,得到相同的结果



此时,a和b相差256


接下来我们检查一下我们计算机上最大的unsigned int 和signed int的值



也就是2的32次方减一,我们拿最大的2的32次方加上121(就是a=4294967417)看看得到什么结果



咦居然还是y!!!为什么为什么呢??呵呵我们先慢慢分析以上这几种情况




为什么呢?


呵呵,记住一句话“你遇到的代码问题都是代码本身帮你解决的”,我们现在看代码中很隐蔽很重要的一句话


printf(“a :%c”,a);


这句话就是关键!首先要知道char类型的数据宽度是多少?一个字节,然后所有的问题都解决了




我特意对齐了这些数据的二进制表示的最低位,有助于帮助你理解。看见了吧,最低的七位都是相同的对应的,然而这句要命的


printf(“a :%c”,a);


将a原本的int类型(不管什么int类型),强制类型转换成了char型数据,于是乎,数据宽度缩小到八位,大于八位的统统溢出,最后保留下来的数据就只有后面的八位了,八位相同的二进制数经过ascll码表的转换当然得到相同的字符,于是得到都是输出字符‘y’的结果


以上是当a,b为正数时的情况分析,如果当被强制类型装换的int变量为负数时则需要分情况讨论,

(注意此代码中的第二个%c后面空格)

177和178均为越界的数,那么均打印字符‘?’,原因在于编译器规定凡溢出截断处理后,



1.   不落在0-127(VC6.0中的ascll码表为标准ascll码不含扩展)之间的,都打印字符‘?’,



2.    凡是落在0-127之间的安照标准ascll码打印字符



我还发现一个奇特的现象


将两个连接着的%c之间的空格去除,则打印出了一个汉字,这可能是和汉字转码表有关了,%c%c两者的截断可能被连接起来一起转码,于是转码出了汉字,这里可以联系以前的基础知识,为什么英文字母都是一个字节(八个位),而汉字要两个字节(此处%c%c连接起来恰好两个字节)


双引号内的空格是有意义的,起到间断 位 的作用










                                                                                                                               ——The.L

                                                                                                                                于2013.03.31XTU

0 0
原创粉丝点击