short
变量的值超过范围
在C语言中整数是用补码的形式进行存储。不同整数类型占据不同的内存空间。
比如:short
型变量占据2B
,表示的数据范围是-32768~32767
,在 这个范围内可以进行正常的数值运算。
但是如果不小心让short
变量的值超过这个范围,会如何?
short m;
m=32768;
printf("%d",m);
十进制32768在内存存储为1000 0000 0000 0000
。
执行printf("%d",m);
,编译器便到内存找到m对应的值1000 0000 0000 0000
。接下来它这样做:
开头是1,是负数;然后减1,各位取反,得到1000 0000 0000 0000
,将其转为十进制,是32768。于是m=-32768。
再举个例子
short m;
m=-32769;
printf("%d",m);
会输出什么?
首先,-32769
在内存中是什么样的?1000 0000 0000 0001
or0111 1111 1111 1111
?
负数存的是它的补码,-32769
的补码是后者。
接着要执行printf("%d",m);
了,编译器从内存找到变量m
的值0111 1111 1111 1111
。
编译器是这样处理的:开头是0
,是正数。直接将其转为十进制,便是32767
。
signed short
类型转为unsigned short
我们在学到类型转换的时候,无符号的优先级大于有符号的。如:一个signed int
+unsigned int
结果是unsigned int
型,即signed int
会先转为unsigned int
,然后再运算。
有符号和无符号的存储范围不一样,如:
signed short | -32768~32767 |
---|---|
unsigned short | 0~65,536 |
short m=32768;
unsigned short n;
n=m;
printf("n=%d",n);
32768存为1000 0000 0000 0000
。
编译器取到这个数据后怎么做?和上面步骤一样,但是第一步省略,即不判断正负,直接转为十进制。所以n
和m
的值相同。
short m=-32769;
unsigned short n;
n=m;
printf("n=%d",n);
输出什么?
short
类型转为int
类型
short
是2B,int
是4B,内存空间不一样。将short
转为int
,如果是:0101 1111 1011 0000
,则会转为0000 0000 0000 0000 0101 1111 1011 0000
;如果是1101 1111 1011 0000
,则会转为:1111 1111 1111 1111 1101 1111 1011 0000
。本质就是,第一位是0
,那么前面补两个字节的0
;第一位是1
,前面补两个字节的1
。
我们用强制转化换测试一下
short m=24496;
printf("%d",(int)m);
m在内存存为:0101 1111 1011 0000
(int)m
,那么0101 1111 1011 0000
就变成了0000 0000 0000 0000 0101 1111 1011 0000
所以输出和原来一样,只是占据的内存量变大了2B
。
再看个例子
short m=-32770;
printf("%d",(int)m);
输出什么?
是-32770
吗?
分析一下:
-32770
在内存以补码形式存储,存储内容为:0111 1111 1111 1110
0111 1111 1111 1110
存在4B
的空间中变成了0000 0000 0000 0000 0111 1111 1111 1110
0000 0000 0000 0000 0111 1111 1111 1110
第一位是0
,故直接转为十进制,是32766
。
这里容易造成的误解是,认为int
的范围比short
大,那么超过short
范围的数值可以当做正常的int
数据,所以认为-32770
变成int
型后可以输出-32770
。
但看了内在的机制后便不会这样认为了。
类型转换中的误解
short
型数据和short
型数据进行四则运算,结果是int
型。
输出是4
,说明a+b
这个表达式的结果是int
型,因为short
型是输出2
.
编译a+b
,会先将a
,b
转为int
型,然后再进行加法。
但是之后a
和b
是什么类型,int
吗?
其实还是short
。这便是容易产生误解的地方。自动类型转换和强制类型转换只是在运算时进行转,但是不会改变变量本来的类型。
Over!