首页 > 学院 > 开发设计 > 正文

C中的有符号数和无符号数之间的转换

2019-11-08 19:43:28
字体:
来源:转载
供稿:网友

1. 在C语言中,数字常量如果没有后缀‘U'或'u',则默认为是有符号。

例:

[cpp] view plain copyunsigned int n = 1024;   unsigned int m = 0XFF;  

其中1024和oxff这两个常量都是有符号数,这就意味着每个赋值操作包含了一个隐式的由有符号数到无符号数的类型转换。而1024u和0xffu则视为无符号数。

2. 同类型整数之间的类型转换:

这样的类型转换是指不同字长的无符号数或有符号数之间的类型转换,如由short转为int,或是有unsigned short转换为unsigned。无符号数由短变长使用零扩展,使用0来填充多出来的高字节。

例:

[cpp] view plain copyunsigned char a = 178;  unsigned short b = a;  

a的二进制表示为1011,0010,b的二进制表示为0000,0000,1011,0010,这就是零扩展。零扩展对于应汇编(ia32)指令movz。

有符号数一般使用补码表示,有符号数的由短变长的转换使用符号扩展,即较短的数的二进制表示的最高位是0则用零扩展,同无符号数的零扩展,而如果是1,则用1来补充缺少的位。

例:

[cpp] view plain copychar a = -78;  short b = a;  

a的二进制表示为1011,0010,b的二进制表示为1111,1111,1011,0010。当然,此时b的大小仍是-78。而由长变短则更简单,直接截断即可,高位的字节直接丢掉,低位的字节保持不变。

3. 有符号数和无符号数之间进行类型转换:

[cpp] view plain copya = (int)b; // 显示的强制类型转换  b = a;      // 转换是隐式发生的  

当发生有符号数和无符号数之间的强制类型转换时,如果他们的长度是相同(比如int和unsigned一般都是4个字节,short和unsigned short都是两个字节),那么在位一级的表示上并没有变化,即如果都转化为二进制的形式来看,都是一样的。虽然从二进制01组成的角度来看是一样的,但我们要知道有符号数和无符号数的区别是最高位的权值发生了变化,有符号整数用补码表示,最高位的权值是-2^(w-1),w为位宽,如int类型w大小为32,而无符号整数的最高为的权值为2^(w-1)。而如果两个数长度不同,则先进行前面提到的2中长度的转换,再进行类型转换。

4. 有符号数和无符号数在一起进行运算时,要首先将有符号数转换为无符号数,再进行运算。

例:

[cpp] view plain copyshort n = -1;  unsigned short m = 1;  if(m > n) PRintf("m > n");  else printf("m < n");  

这样可以得到什么结果呢?

首先n转化为无符号数,大小为65535,所以输出是m<n。

5. 整型常量

在1中我们说,如果一个常数没有后缀,那么默认的是int类型,如果后缀是u,则默认为unsigned int。但这样的说法并不完整。

首先,我们默认了常数的格式是十进制,但是十六进制的也很常用。

然后,还可能出现这样的情况:给出的常数的值已经超越了int或是unsigned int的范围。这种情况又该如何处理?

可能目前为止都没有遇到过这种情况,但是如果发生该如何理解呢?别急,C标准对这些情形都给出了明确的说明,了解之后你就会知道为啥不知道耶没有发生错误。

看完下面这张表你也许悟到了点啥,莫名其妙也没关系,让我们来细说一例:

“十进制常数”和“none”后缀的对应的格子里的内容是:

int

long int

long long int

这三行的意思是对于没有后缀的十进制常数,如1024和3147483647,首先用int类型来匹配,int类型值得范围是-2147483648~2147483647,1024在此范围之内,那么这个常数的类型就是int了,但3147483647不在此范围之内,即int类型罩不住,那么看第二行,long int类型,其范围还依赖于机器的字长,一般32位机上为-2147483648~2147483647,还是罩不住,再看第三行,long long int,其范围是-9223372036854775808到9223372036854775807,所以3147483647最终匹配的类型是long long int。

对于八进制或十六进制的常数,如果没有后缀,会先匹配有符号数,再匹配无符号数,毕竟从取值的绝对值的范围的角度上看无符号数更广。

如果一个常数大的表中没有任何类型能够表示,那么就要看有没有扩展类型能够表示它,如果没有,那么这个常数没有类型。

Suffix 后缀Decimal Constant 十进制常数Octal or Hexadecimal Constant 八或十六进制常数
noneintlong intlong long intintunsigned intlong intunsigned long intlong long intunsigned long long int
u or Uunsigned intunsigned long intunsigned long long intunsigned intunsigned long intunsigned long long int
l or Llong intlong long intlong intunsigned long intlong long intunsigned long long int
Both u or Uand l or Lunsigned long intunsigned long long intunsigned long intunsigned long long int
ll or LLlong long intlong long intunsigned long long int
Both u or Uand ll or LLunsigned long long intunsigned long long int

参考CSAPP和C99


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表