代码改变世界

有符号数与无符号数的转换

2017-07-26 17:47  ZengGW  阅读(9155)  评论(0编辑  收藏  举报

c支持所有数据类型的有符号与无符号运算,尽管c标准没有明确指定某种有符号数的表示,但是几乎所有的机器都使用二进制补码

大多数数字默认是有符号的,当咱们声明一个12345或者0x123,这其实都是有符号的

c在同时包含有符号和无符号的运算,c会把有符号的运算数隐含转换成无符号的运算数(只要含有无符号的数,其他的有符号的数都会被隐含的转换成无符号的数)

一、创建无符号的常量

  在常量的后边加上后缀字符“U”或者“u”,比如 12345U 或者 0x123u(大小写都行)

二、转换

  c允许有符号与无符号之间的转换,原则是基本的位表示保持不变;

  1.无符号转换成有符号,效果就是应用了函数U2Tw其中w表示数据类型的位数

  U2Tw = -xw-12W + X;

  ,从这里可以看出,当 0 <= x < 2w-1的时候是正数,则转换的过程中保持不变; 当 x >= 2w-1的时候,结果是x - 2w,

  下面是示意图:

     

  结论:

    1>. 对于小的数(< 2w-1):从无符号到有符号的转换将保留数字的原值;

    2>.对于大的数(>= 2w-1):从无符号到有符号的转换,数字将被转换为一个负数值

  比如:2147483648U,在输出的时候为什么是-2147483648,

  过程:因为2147483648 >= 2(32-1),也就是说,它是大的数(>= 2w-1),按照U2Tw的规则,2147483648 - 232 = -2147483648

  2.从有符号转换成无符号,效果就是应用了函数T2Uw其中w表示数据类型的位数

    T2Uw = xw-12W + X;

    从这里可以看出,当 x >= 0的时候是正数,则转换的过程中保持不变; 当 x < 0的时候是负数,结果是x + 2w

  下面是示意图:

    

  结论:

    1>.非负数:保持不变

    2>.负数:被转变成了大的正数,也就是x + 2w

  比如:-1 

  过程:根据函数规则,负数 -1 + 232 = -4294967297

 三、注意事项(下面的观点有误)

  1.先看几个练习题:

    a. -2147483648 == 2147483648U

    b. -2147483648  < -21474836487

    c. (unsigned) -2147483648 < -21474836487

    d. - 2147483648 < 21474836487

    e.(unsigned) -2147483648 < 21474836487

  示例:

     前面提到过我们创建的数字常量啥的默认都是有符号的,声明无符号的常量在后边加上后缀“U”或者“u”,当两个数进行运算时,只要有无符号数,那么另一个有符号数也会被隐含的转换成无符号数,还有一点,那就是针对超出系统指定位数正数范围的数,在转换的时候,高位是要被舍去的,比如:在8位机器上边,最大的无符号正数也才255,那300,在比较的时候怎么转换呢?

    比如 (unsigned) -127 < 300

    过程:首先有unsigned声明是无符号的,那么整个运算类型是无符号的,那先来转换一下,-127(有符号转无符号T2Uw)转成无符号的是 -127 + 28 = 129; 那300呢?本身它是个正整数,但是它超出系统8位机最大的unsigned int值(INT_MAX = 255),咱们先把300转成2进制(100101100),从这个二进制可以看出,它是9位,根据系统位数,超出最大范围的数,二进制的最高位要被舍去,保留8位,结果是00101100 = 44,结果可想而知(unsigned) -127(129) < 300(44) 的结果是0

  分析练习题: 

    a. -2147483648 == 2147483648U;2147483648U后缀是“U”,则根据规则 该运算的类型是无符号的,-2147483648根据规则转换成无符号的(-2147483648 + 232 = 2147483648 ),而2147483648由于刚好等于231,而2147483648U它是无符号的,

    b. -2147483648  < -21474836487;该运算是有符号类型,同事有符号且是负数的进行比较,这里不难看出来其实-2147483648 > -21474836487,所以结果是0