关于C语言中的无符号数和有符号数

无符号数和有符号数是不能进行比较运算的,否则可能会出现意想不到的错误,且极难检查出来!
首先肯几个例子(假设在32位的机器上):
1           1 0   ==   0U
2           2 - 1   <   0U  (注: 0是无符号的)
3           3 2147483647U   >   - 2147483647   -   1
4           4 2147483647   >  ( int 2147483648U

 

结果如下:
1           1 1
2           2 0   *
3           3 0   *
4           4 1   *

 

从结果中可以看出,2 3 4都不是我们想像中的结果。在C语言中,当一个无符号数和一个有符号数进行比较运算时,有符号数会被隐含的转换成无符号数,并假设这两个数都是非负数,然后进行比较运算。当把一个有符号数转换成无符号数时,其底层的二进制表示没有改变,仅仅是对其进行了不同的解释。这样,由于这两个原因就会出现上面的结果。
首先分析一下2:
-1的二进制补码表示是32个1。而0U的二进制补码表示是32个0.在比较的时候,-1被当做无符号数,也就是把32个1当做无符号数和32个0的无符号数比较,显然,32个1要大于32个0.所以,2的结果是1.
再看看3,-2147483647的二进制补码表示是1000 0000 0000 0000 0000 0000 0000 0000, -1的补码表示是32个1,两个相加,也就是补码异或,得到0111 1111 1111 1111 1111 1111 1111 1111,这个结果是溢出的。由于前一个的操作数是无符号数,因此,前面的计算结果被当做无符号数来处理,因此,这两个数是相等的。所以结果是0.对于4,2147483648U被转换成有符号数是-1,所以4的结果是1.
从上面可以看出,无符号数和有符号数在进行比较的时候,如果数值在边界上,则很容易出错。
看下面的一段程序:
 1  float  sum( float  a[], unsigned  int  len)
 2  {
 3       int  i;
 4       float  r  =   0.0 ;
 5       for  (i  =   0 ; i  <=  len  -   1 ++ i)
 6      {
 7          r  +=  a[i];
 8      }
 9       return  r;
10  }

 

如果len为0,那么这段代码将不会返回0.0。而是段错误。

另外,当在无符号数和有符号数之间进行类型转换时,不同的转换顺序会得到不同的结果。如:
1 
2  unsigned x  =   0xFFFF ;
3  ( int ) ((word  <<   24 >>   24 );
4  (( int ) word  <<   24 >>   24 ;

 

        第一个表达式的结果是0xFF,而第二个是0xFFFFFFFF.原因是第一个表达式的右移运算高位补0,而第二个右移运算高位补1.

测试代码:
 1  #include  < stdlib.h >
 2  #include  < stdio.h >
 3  float  sum( float  a[], unsigned  int  len)
 4  {
 5       int  i;
 6       float  r  =   0.0 ;
 7       for (i  =   0 ; i  <=  len  -   1 ++ i)
 8      {
 9          r  +=  a[i];
10      }
11      
12       return  r;
13  }
14 
15  int  main()
16  {
17      printf( " -1 < 0U : %s\n " , ( - 1   <   0U ?   " true "  :  " false " );
18      printf( " 2147483647U > -2147483647 - 1 : %s\n " , (  2147483647U   >   - 2147483647   -   1 ?   " true "  :  " false " );
19      printf( " 2147483647 > (int)2147483648U : %s\n " , (  2147483647   >  ( int ) 2147483648U ?   " true "  :  " false " );
20      
21      unsigned w  =   0xFFFF ;
22      printf( " (int) ((w << 24) >> 24) = %x\n " , ( int ) ((w  <<   24 >>   24 ));
23      printf( " ((int)(w << 24)) >> 24 = %x\n " , (( int )(w  <<   24 ))  >>   24 );
24 
25       float  a[ 1 ];
26      printf( " sum %f\n " , sum(a,  0 ));
27       return   0 ;
28  }

 

运行结果:
1  hcy@hcy - desktop: ~ $ . / a. out  
2  - 1   <   0U  :  false
3  2147483647U   >   - 2147483647   -   1  :  false
4  2147483647   >  ( int ) 2147483648U  :  true
5  ( int ) ((w  <<   24 >>   24 =  ff
6  (( int )(w  <<   24 ))  >>   24   =  ffffffff
7  段错误

 

 

 

转载于:https://www.cnblogs.com/kernel_hcy/archive/2010/01/06/1640152.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值