Chinaunix首页 | 论坛 | 博客
  • 博客访问: 76160
  • 博文数量: 17
  • 博客积分: 789
  • 博客等级: 军士长
  • 技术积分: 145
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-01 17:46
文章分类
文章存档

2010年(17)

我的朋友

分类: C/C++

2010-07-22 13:06:54

#include "stdio.h"

int array[] = {1,2,3,4,5,6};
#define TOTAL_ELEM sizeof(array)/sizeof(array[0])


int main(int argc, char* argv[]) {
    int d = -1;
    printf("total_elem = %d\n",TOTAL_ELEM);
    if (d <= TOTAL_ELEM)
        printf("samll\n");
    else printf("large\n");
    return 0;
}


上述代码,我们理所当然的认为应该输出small,但是程序实际的运行结果确实输出了large。这个诡异的问题是因为C语言重的类型转换的问题引起的。

TOTAL_ELEM所定义的值是unsigend int类型(因为sizeof()的返回值是unsigned int类型)。if语句在signed int和unsigned int类型之间作比较,会自动的将signed int提升为unsigned int类型,而-1转换为无符号整形是个很大很大的数,所以就出现了上面的诡异的BUG。

采用通俗的语言来描述ANSI C标准所定义的类型提升如下所述:
当执行算数运算的时候,操作数的类型不同,就会发生转换,数据类型一般朝着浮点精度更高,长度更长的方向转换,整形数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。

所以在《C专家编程》重,作者对于我们使用无符号类型的建议是
1、尽量不要在代码中使用无符号类型,以避免增加不必要的复杂性。尤其是,不要仅仅因为无符号数不存在负数,而使用它表示数量
2、尽量使用像int那样的有符号类型,这样涉及升级混合类型的复杂细节时,不必要担心边界情况(如-1被翻译成很大的正数)。
3、只有在使用位段和二进制掩码的时候,才可以使用无符号数。应该在表达式中使用强制类型转换,是操作数均为有符号数或者无符号数,这样就不必由编译器来选择结果。
阅读(1440) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~