本节描述两种整数的表示方式,一种只能表示非负数(无符号整数),一种都能表示(有符号整数)。
整数类型和表示范围
C数据类型 | 最大值 | 最小值 |
---|
char | -128/SCHAR_MIN | 127/SCHAR_MAX | unsigned char | 0/CHAR_MIN | 255/UCHAR_MAX | short | -32768 | 32767 | unsigned short | 0 | 65535 | int | -2^31/INT_MIN | 2^31-1/INT_MAX | unsigned int | 0 | 2^32-1 | long(32位) | =int | =int | long(64位) | -2^63 | 2^63-1 | unsigned long(32位) | =unsigned int | =unsigned int | unsigned long(64位) | 0 | 2^64-1 | int32_t | =int | =int | uint32_t | =uint | =uint | int64_t | =long64 | =long64 | uint64_t | =ulong64 | =ulong64 |
为了保证兼容性,应该减少使用long,而用int32_t等代替。
无符号整数
以char为例子,二进制编码为1001 1101的unsigned char类型数据的大小为: 127+026+…+1*20=157
有符号整数
通常大部分数都默认是有符号数,除在定义的时候加unsigned。 对于数字来说在末尾加u或U也可以表示其为无符号:123u,0xa2U
补码
最常见的有符号表示方式就是补码。设置最高有效位为符号位,0表示整数,1表示负数。 同上一个char的例子,二进制编码为1001 1101的char类型数据的大小为: -127+026+…+1*20=-99
99的二进制编码为01100011。可以看出从99变成-99,或者从-99变成99,就是二进制编码取反再+1。
无符号和有符号的转换
C语言允许各种不同类型之间的强制转换。
在无符号和有符号的转换时,数据的位(二进制表示)不会变化,只是解释这二进制的方式变了。 如signed char a = -1;其二进制表示为:1111 1111 将其转换unsigned char b = a;其二进制表示不变,但值为255
当有符号和无符号混合运算的时候,C会将有符号隐式转为无符号数和无符号数就行运算。这在算数运算的时候可能没什么问题,但是在大小于这样的运算会出现问题。
扩展数字的位表示
例如将short类型的数据变成int类型 无符号数:在前面补0 有符号数:在前面补最高位的值
当把short转为unsigned int时,会先改变大小(把short转为int),再改变符号(把int变成unsigned int)
截断数字
例如把int变成short。 书上讲了一大堆,我觉得就是把高位的丢掉。
建议
有符号和无符号的数据表示范围不同,在使用和运算的过程中总是不小心就有隐式转换的发生,造成一些细节的错误。 书上建议在编程的时候别用无符号数。 但是在一些特定的场合如bitmap、系统编程的时候还是有它的作用的。
|