-
(从原来的博客贴过来的)
#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