【问题标题】:sizeof() operator in if-statementif 语句中的 sizeof() 运算符
【发布时间】:2013-06-25 09:31:11
【问题描述】:
#include <stdio.h>
int main(void)
{
    if (sizeof(int) > -1)
        printf("True");
    else
        printf("False");
}

它打印False。为什么 sizeof() 不返回 if 中的值?

【问题讨论】:

  • 启用编译器警告。
  • (sizeof(int) &gt; -1) = (4u &gt; -1) = (4u &gt; -1u) = (4u &gt; -1u)(4u &gt; 4294967295uu) 因为-1u == 4294967295u = False = 0
  • int main()。不仅仅是main()

标签: c sizeof


【解决方案1】:
  1. sizeof 不是函数,而是运算符。括号不是运算符名称的一部分。
  2. 它失败了,因为生成的值具有无符号类型size_t,这会导致“通常的算术转换”,其中-1 被转换为无符号,在这种情况下它是一个非常大的数字。

基本上,您是在比较 4 &gt; 0xffffffffu,或者至少与之接近的东西。 See this question了解详情。

【讨论】:

  • 严格来说,这里没有整数提升,而是平衡(正式称为“常用算术转换”)。
  • -1 转换为无符号整数类型总是产生最大值,即使表示不是二进制补码
  • 您的第一点是正确的,但无关紧要。返回 size_t 的函数也是如此。
  • 只是为了吹毛求疵:如果sizeof sizeof 1 &lt; sizeof 1sizeof(int)&gt;-1 将是true
  • @ugoren 是的,当然。我只是努力,呃,教人们这个事实,因为这么多 C 编程的人似乎误解了它,这很烦人。可能是我狂妄自大的标志。
【解决方案2】:

无符号和有符号整数提升(更准确地说是“通常的算术转换”)。 sizeof 产生一个 size_t 类型的值,当与无符号值(size_t 是)比较时,-1 被提升为该类型,并溢出并变成 巨大的。

无符号整数溢出具有明确定义的行为,将被视为模2 ^ width,其中width 是特定无符号整数类型中的位数。因此,如果您有一个 32 位宽的 size_tint,例如,您的比较将等同于

if (4 > 4294967295u)

这显然是错误的。

【讨论】:

  • 很好的答案,但它不是下溢而不是上溢吗?
  • @C0deH4cker 好吧,这完全取决于您如何解释它:) 当某些x &lt; epsilon 数字变为零时,我更喜欢将“下溢”用于浮点数。如果您从模算术的角度考虑这种现象(无论如何都是这样定义的),那么“溢出”在这里更容易理解。
  • 啊,好吧,这个答案 (programmers.stackexchange.com/questions/32893/…) 解释了它以及我为什么感到困惑。
【解决方案3】:
  • if语句中>运算符的操作数是sizeof(int)-1
  • sizeof(int)size_t 类型,保证为无符号整数。在实践中,size_t 在任何系统上很可能至少与unsigned int 一样大。
  • -1 的类型为 int,相当于 signed int
  • 不会发生整数提升,因为两个操作数都是足够大的整数类型。
  • 然后根据正式称为常用算术转换的 C 规则平衡两个操作数。

这些状态(C11 6.3.1.8):

...

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

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

  • 将发生上述后者,因为(签名的)int 不能适合 size_t 的所有值。
  • 因此-1 被转换为无符号整数。在实践中,size_t 很可能等同于 unsigned int 或 unsigned long。将 -1 存储在此类变量中时发生的任何情况都是实现定义的行为。
  • 在二进制补码计算机(世界上所有计算机的 99.9%)上,-1 将被解释为 0xFFFFFFFF(FF 的数量取决于给定系统上 int 的大小)。
  • 4 &gt; 0xFFFFFFFF 计算结果为假。

【讨论】:

  • “当您将 -1 存储在这样的变量中时发生的任何事情都是实现定义的行为。”嗯,这里唯一依赖于实现的是size_t 的宽度。标准要求将-1 转换为无符号类型以产生该类型的最大值。
  • @DanielFischer 我的意思是,有符号整数行为的方式是 impl.defined。 C 允许补码、补码等。
  • 其中“等等”扩展为“有符号的幅度”或“符号和幅度”,具体取决于您喜欢的名称。因此,转换是否只是截断/重新解释/符号扩展或以不同方式更改位模式是实现定义的,是的。但这无关紧要,不是吗?重要的是结果。
  • @DanielFischer 结果取决于签名方式。 -1 会给你 0xFFFFFFFE。由于我在示例中使用了 0xFFFFFFFF,因此我想指出,严格来说,-1 不能保证为 0xFFFFFFFF。否则有人会发表评论并对此抱怨,因为 C 也允许使用晦涩的签名格式。
  • 虽然-1 的位模式不必是0xFF..F,但-1(从有符号整数类型)转换为无符号整数类型的结果总是(嗯,除非宽度不是 4 的倍数)具有位模式0xFF...F。这是标准 [模 as-if 规则] 规定的。
【解决方案4】:

Sizeof 是一个产生 unsigned long int 的运算符。因此,当您将 unsigned long int 与 -1 进行比较时,它存储为 0xffffffff(int 的大小为 4 个字节)。

-1 默认为有符号整数。但是,与有符号整数和无符号整数相比,编译器将有符号整数隐式类型转换为无符号整数。这导致 unsigned -1 大约等于 4.6giga 值。

因此,输出为false

【讨论】:

    【解决方案5】:

    只需测试一下,自己看看

    #include <stdio.h>
    main() {
        unsigned int a=4;
        int b = -1;
        //this is what you're doing
        printf("%u vs %u\n", a, (unsigned int)b);
        //this is what you want to do instead
        printf("%d vs %d\n", (int)a, b);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-08
      • 2015-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2012-11-04
      相关资源
      最近更新 更多