嵌入式编程常考的无符号数和有符号数的运算问题

1、有符号数与无符号数之间运算问题
  以下实验均在virual c++6中运行通过
  这个问题测试是否懂得C语言中的整数自动转换原则,有些开发者懂得极少这些东西。当表达式中存在有符号类型和无符号类型时 所有的操作数都自动转换为无符号类型。因此,从这个意义上讲,无符号数的运算优先级要高于有符号数,这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。 
首先进行一个实验,分别定义一个signed int型数据和unsigned int型数据,然后进行大小比较:
    unsigned int a=20;
    signed int b=-130;
a>b?还是b>a?实验证明b>a,也就是说-130>20,为什么会出现这样的结果呢?
   这是因为在C语言操作中,如果遇到无符号数与有符号数之间的操作,编译器会自动转化为无符号数来进行处理,因此a=20,b=4294967166,这样比较下去当然b>a了。
再举一个例子:
 unsigned int a=20;
 signed int b=-130;
 std::cout< 结果输出为4294967186,同样的道理,在运算之前,a=20,b被转化为4294967166,所以a+b=4294967186


  减法和乘法的运算结果类似。
  如果作为signed int型数据的b=-130,b与立即数之间操作时不影响b的类型,运算结果仍然为signed int型:
signed int b=-130;
std::cout< 输出为-100。

       而对于浮点数来说,浮点数(float,double)实际上都是有符号数,unsigned 和signed前缀不能加在float和double之上,当然就不存在有符号数根无符号数之间转化的问题了。

2、#include
int main()
{
    unsigned int a = 1;
    signed int b = -2;


    printf("%d\n", a + b);
    printf("%u\n", a + b);
  
    return 0;
}

       计算机中的加法运算是通过加数补码相加实现的。
       程序中,a为无符号整型数,其补码为0000 0001(方便起见,这里仅用8位表示,下文同理),起始位的“0”表示数值;b为有符号整型数,其补码为1111 1110,起始位的“1”表示正负。
        将变量a和变量b的补码相加,得到1111 1111。
          printf("%d\n", a + b)中,由于%d的作用,使a+b以有符号十进制的形式输出,此时,最高位的1为符号位,减一取反得到其原码,得到1000 0001,即十进制的-1;
         printf("%u\n", a + b)中,由于%u的作用,使a+b以无符号十进制的形式输出,此时,最高位的1并非符号位,其表示数值大小,不用减一取反,得到1111 1111,实际Linux系统中,该数用4个字节表示,也就是说实际上这里有16个"1",即十进制数的4294967295(=2^32-1)。
        综上,该段程序的输出结果为:
                                                         -1
                                                         4294967295

3、#include 
int main() 

        unsigned int a=6; 
int b=-20; 
printf("%d\n",a+b); 
(a+b)>6? puts(">6"):puts("<=6"); 
return 0; 

结果是:-14  >6
意想不到吧?为什么结果这样呢?
原来有符号数和无符号数进行比较运算时(==,<,>,<=,>=),有符号数隐式转换成了无符号数(即底层的补码不变,但是此数从有符号数变成了无符号数),比如上面 (a+b)>6这个比较运算,a+b=-14,-14的补码为1111111111110010。此数进行比较运算时,被当成了无符号数,它远远大于6,所以得到上述结果。

reference:http://blog.csdn.net/supreme42/article/details/6687781

你可能感兴趣的:(linux编程学习,linux)