【问题标题】:C Treament when Casting Comparison Values转换比较值时的 C 处理
【发布时间】:2014-02-04 20:51:03
【问题描述】:

有人和我谈论 C 中的环绕 (0xffff + 0x0001 = 0x0000),这导致我遇到以下情况:

int main() {
  unsigned int a;
  for (a = 0; a > -1; a++)
    printf("%d\n", a);
  return 0;
}

使用 GCC 编译,该程序退出而不运行循环,我认为这是因为 -1 被隐式转换为 0xffff。将int 切换到long 时也会发生同样的情况。但是,当切换到char 时,程序会无限期地运行。我希望由于int 没有运行循环,char 也不会。有人能解释一下编译器在这种情况下执行什么样的隐式转换,它是在 C 标准的某个版本中定义的,还是依赖于编译器的?

【问题讨论】:

    标签: c casting comparison implicit-conversion


    【解决方案1】:

    在 C 中,无符号是粘性的:

      unsigned int a;
    
      /* ... */
    
      a > -1
    

    在上面的> 表达式中,左操作数的类型为unsigned int,右操作数的类型为int。 C 常用的算术转换将两个操作数转换为通用类型:unsigned int,因此上面的 > 表达式等价于:

     a > (unsigned int) -1
    

    -1unsigned int 的转换使得结果值成为一个巨大的 unsigned int 值,并且由于 a 初始值为 0,表达式被评估为 false (0)。

    现在,如果 a 的类型为 charint,则 -1 不会转换为 unsigned int,因此 0 > -1 为 true (1) 符合预期。

    【讨论】:

      【解决方案2】:

      引用自ISO/IEC 9899:

      如果两个操作数都有算术类型,通常的算术转换是 执行。

      多个运算符自动将操作数值从一种类型转换为另一种类型。

      许多期望算术类型操作数的运算符会导致转换并产生结果 以类似的方式键入。目的是确定操作数的通用实数类型 和结果。对于指定的操作数,每个操作数都进行转换,不改变类型 域,到对应的实类型是公共实类型的类型。除非 另有明确说明,公共实类型也是对应的实类型 结果,其类型域是操作数的类型域(如果它们相同), 否则复杂。这种模式称为通常的算术转换:

      首先,如果任一操作数对应的实数类型是long double(...)

      否则,如果任一操作数对应的实数类型为double(...)

      否则,如果任一操作数对应的实数类型为float(...)

      否则,整数提升将在两个操作数上执行。然后 以下规则适用于提升的操作数:

      如果两个操作数的类型相同,则不需要进一步转换。

      否则,如果两个操作数都具有有符号整数类型或都具有无符号 整数类型(...)

      否则,如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的等级,然后操作数与 有符号整数类型转换为无符号操作数的类型 整数类型。

      否则,如果带符号整数类型的操作数的类型可以表示 无符号整数类型的操作数类型的所有值,然后 将无符号整数类型的操作数转换为 带符号整数类型的操作数。

      否则,两个操作数都转换为无符号整数类型 对应有符号整数类型的操作数的类型。

      【讨论】:

      • 那么,在应用此之前,文字是否会转换为signed int
      • @Tanaki 是的,Mr.ouah 告诉你如何做一个例子。
      【解决方案3】:

      基本上,当您在 C 中执行操作时,该操作必须在至少与较大运算符一样大的基数中执行。

      所以,假设你的 int 是一个 int32,那么操作:

      uint32_t > int32_t
      

      该操作必须在基础“uint32_t”或更高版本中执行。在这种情况下,它正在“uint32_t”中执行。

      当你这样做时:

      uint8_t > int32_t
      

      该操作正在基“int32_t”或更高版本中执行。

      通常,如果可能,操作将在“int”基础中执行,因为它应该比任何其他基础都快。

      所以,如果你这样做:

      (int)unsigned char > int(-1)
      

      ,条件永远为真。

      【讨论】:

        猜你喜欢
        • 2012-04-05
        • 1970-01-01
        • 2011-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-18
        • 1970-01-01
        • 2014-04-09
        相关资源
        最近更新 更多