例:
例:
a的二进制表示为1011,0010,b的二进制表示为0000,0000,1011,0010,这就是零扩展。零扩展对于应汇编(ia32)指令movz。
有符号数一般使用补码表示,有符号数的由短变长的转换使用符号扩展,即较短的数的二进制表示的最高位是0则用零扩展,同无符号数的零扩展,而如果是1,则用1来补充缺少的位。
例:
而由长变短则更简单,直接截断即可,高位的字节直接丢掉,低位的字节保持不变。
当发生有符号数和无符号数之间的强制类型转换时,如果他们的长度是相同(比如int和unsigned一般都是4个字节,short和unsigned short都是两个字节),那么在位一级的表示上并没有变化,即如果都转化为二进制的形式来看,都是一样的。虽然从二进制01组成的角度来看是一样的,但我们要知道有符号数和无符号数的区别是最高位的权值发生了变化,有符号整数用补码表示,最高位的权值是-2^(w-1),w为位宽,如int类型w大小为32,而无符号整数的最高为的权值为2^(w-1)。而如果两个数长度不同,则先进行前面提到的2中长度的转换,再进行类型转换。
例:
这样可以得到什么结果呢?
首先n转化为无符号数,大小为65535,所以输出是m
在1中我们说,如果一个常数没有后缀,那么默认的是int类型,如果后缀是u,则默认为unsigned int。但这样的说法并不完整。
首先,我们默认了常数的格式是十进制,但是十六进制的也很常用。
然后,还可能出现这样的情况:给出的常数的值已经超越了int或是unsigned int的范围。这种情况又该如何处理?
可能目前为止都没有遇到过这种情况,但是如果发生该如何理解呢?别急,C标准对这些情形都给出了明确的说明,了解之后你就会知道为啥不知道也没有发生错误。
看完下面这张表你也许悟到了点啥,莫名其妙也没关系,让我们来细说一例:
“十进制常数”和“none”后缀的对应的格子里的内容是:
int
long int
long long int
这三行的意思是对于没有后缀的十进制常数,如1024和3147483647,首先用int类型来匹配,int类型值得范围是-2147483648~2147483647(这里可以看出有符号整型的范围不是对称的,而且此处默认int类型为32位),1024在此范围之内,那么这个常数的类型就是int了,但3147483647不在此范围之内,即int类型罩不住,那么看第二行, long int 类型, 其范围还依赖于机器的字长,一般32位机上为-2147483648~2147483647,还是罩不住,再看第三行,long long int,其范围是-9223372036854775808到9223372036854775807,所以3147483647最终匹配的类型是long long int。
对于八进制或十六进制的常数,如果没有后缀,会先匹配有符号数,再匹配无符号数,毕竟从取值的绝对值的范围的角度上看无符号数更广。
如果一个常数大的表中没有任何类型能够表示,那么就要看有没有扩展类型能够表示它,如果没有,那么这个常数没有类型。
-2147483648这个常数会是什么类型?不一定是int类型,这还要看编译器,很可能编译器会把它当成一个64位的有符号整型(可能是long long int),或者说该编译器在识别常数时可能认为int类型的范围是-2147483647~2147483647,但是我们应该知道32位的int类型是可以表示-2147483648。所以求int类型的绝对值也不那么简单,需要考虑这种情况。
Suffix 后缀 |
Decimal Constant 十进制常数 |
Octal or Hexadecimal Constant 八或十六进制常数 |
none | int long int long long int |
int unsigned int long int unsigned long int long long int unsigned long long int |
u or U | unsigned int unsigned long int unsigned long long int |
unsigned int unsigned long int unsigned long long int |
l or L | long int long long int |
long int unsigned long int long long int unsigned long long int |
Both u or U and l or L |
unsigned long int unsigned long long int |
unsigned long int unsigned long long int |
ll or LL | long long int | long long int unsigned long long int |
Both u or U and ll or LL |
unsigned long long int | unsigned long long int |
参考CSAPP和C99