zoukankan      html  css  js  c++  java
  • 无符号类型的误导

         近日在写程序时,无意间遇到了错误,经反复推敲和调试,确定了错误就出在无符号类型下,百度许久,总结一下。

          相信很多人都知道关于C语言的标准大致有两种,一个是老的K&R C标准,一个是新的ANSI C标准(当然,这也不能算新了),这两种标准关于一些细节方面有很多的不同,但毕竟标准只允许改正,不允许废除,就像intel 8086的段地址:偏移地址的寻址方式也不得不为了兼容性而一直保留着一样,而C语言标准的改变,有人称之为“安静的改变”。

          这段代码可以告诉你,你现在使用的到底是K&R C还是ANSI C,因为虽然-1的位模式是一样的,但是在这两种不同的编译器下的解释确不尽相同,ANSI C将其解释为负数,而K&R C奇怪的将其解释为正数。

          说奇怪也不算奇怪,因为都是有标准可以参照和拿来解释的:

    K&R C采用无符号保留(unsigned preserving)原则,就是当一个无符号类型与int或更小的整形混合使用时,结果类型是无符号类型。这是个简单的规则,与硬件无关。但是,它却会如上面的例子那样,使一个负数丢失符号位。

    ANSI C采用值保留(value preserving)原则,就是当几个整形操作数像上面例子这样混合使用时,结果类型有可能是有符号数,也可能是无符号数,取决于操作数的类型的相对大小。

          我遇到的问题是这样的,参见下面的例子:

          经过调试发现,原本if判断语句应该成立的地方却不是这样的,然后翻阅sizeof()的介绍时发现其返回值类型为size_t,即unsigned int,而if语句在signed int和unsigned int之间进行大小判断时,d被升级为unsigned int类型,这就导致了-1被强制转换成了一个非常大的数,致使表达式为假。

         其实要修正这个问题也很简单,进行强制类型转换,即:

         经过这一次,需要更正一个观点,不要因为某些数不可能出现负数(如年龄)而想当然的将其定义为无符号数,这样可能会在后面的编程中,莫名其妙的出现上次问题。建议只在使用位段和二进制掩码时,才去使用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号数或者无符号数,不要由编译器去选择结果的类型。

  • 相关阅读:
    第12章,存储类别、链接和内存管理
    第11章 字符串和字符串函数
    第10章 数组和指针
    第9章 函数
    第8章 字符输入/输出和输入验证
    第7章,c语言控制语句:分支和跳转
    第六章,处语言控制语句:循环
    中国互联网发展史
    世界互联网发展史
    世界计算机发展史
  • 原文地址:https://www.cnblogs.com/pang123hui/p/2309958.html
Copyright © 2011-2022 走看看