Chinaunix首页 | 论坛 | 博客
  • 博客访问: 663066
  • 博文数量: 78
  • 博客积分: 4990
  • 博客等级: 上校
  • 技术积分: 1386
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-13 19:25
文章分类

全部博文(78)

文章存档

2010年(6)

2009年(25)

2008年(47)

我的朋友

分类: C/C++

2010-02-08 13:53:17

《C专家编程》中对在使用有无符号数有的使用以下三点建议:
1.尽量不要在你的代码中使用无符号数,以免增加不必需要的复杂性。尤其是,不要仅仅因为无符号数不存在负值(如年龄,国债)而用它来表示数量。
2.尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译为非常大的正数)。
3.只有在使用位段和二进制掩码时,才可以用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号或无符号数,这样就不必由编译器来选择结果的类型。

1,2点可以合成一点,说的其实就是尽量不要使用无符号数,多使用有符号数,而第三点说明了无符号数的适用范围。并强调了在处理表达式的时候是操作数类型一致的原则(同为有符号或无符号),这样可以减少一些麻烦和错误。

另外,ANSI C在对有符号数和无符号数进行运算时也给出了一个标准(我在这里就不谈K&R C中的说法了):
当执行算术运算的时候,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。

下面有几个例子:
1.
#include
#include

int main()
{

    int x = 2;
    char * str = "abcd";
    int y = (x - strlen(str) ) / 2;
       
    printf("%d\n",y);
}
结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值,类型是size_t,也就是unsigned int ,与 int 混合计算时类型被自动转换了,结果自然出乎意料。。。
观察编译后的代码,除法指令为 div ,意味无符号除法,即将-2看做无符号数了。
解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成 idiv 了。

2.

void foo(void)
{
   unsigned int a = 6;
   int b = -20;
   (a+b > 6) ? puts("> 6") : puts("<= 6");
}

这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ”>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式 计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。

阅读(2913) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~