1

考虑代码:

int foo(void)
{
    _Bool b = 1; // is true
    int i = 42;  // mean true in conditions

    if (i == b)
        return 1;
    else if ((_Bool)i == b)
        return 2;
    else
        return 3;
}

根据 C 标准(C99 或 C11),此函数将返回什么?

PS 在带有选项的 GCC 4.7.2 上-std=c99,函数返回 2。

4

3 回答 3

2

它返回2

“通常的算术转换”应用于运算符的操作数==_Bool是转换等级低于intor的无符号类型unsigned int

“通常的算术转换”在C99C11标准的第 6.3.1.8 节“通常的算术转换”中指定(链接是最近的草案)。

i == b中,由于没有浮点操作数,因此“整数提升”适用于两个操作数,将右操作数从_Boolto 提升int并产生 value 1。现在两个操作数属于同一类型,因此不需要进一步转换。Soi == b等价于42 == 1,这是错误的。

(_Bool)i == b中,“整数提升”仍然适用于两个操作数,因此两者都从 转换_Boolint。(从intto_Bool和 back to的转换int会丢失信息,将所有非零值转换为1。)现在两个操作数的类型相同,因此不需要进一步的转换。So(_Bool)i == b等价于1 == 1,这是真的 - 并且函数返回2

(注意:由于我在阅读标准时有些粗心,这是关于此答案的第三次主要编辑。我想这次我做对了。)

在回答评论中的问题时,将fromb == 42u提升为,从而进行比较。由于操作数具有不同的符号但相同的转换等级,因此将有符号的操作数转换为无符号类型。从to转换是微不足道的,产生. 所以比较等价于,这是错误的。b_Boolintintunsigned int1intunsigned int1u1u == 42u

(请注意,==C 中的运算符与其他等式和关系运算符一样,会产生int带有值0or的类型结果1而不是类型的结果_Bool。)

于 2012-12-01T10:29:35.740 回答
0

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

因此,在计算表达式i == b时,会发生算术转换。在算术转换期间,所有涉及的操作数都被转换为所有可以“适合”的最低等级类型,在这种情况下int

由于1 != 42,第一个条件不成立。

第二个表达式首先转换i为 a _Bool,结果为true。然后它评估true == true显然是true。因此函数返回2

于 2012-12-01T10:20:49.640 回答
0

为什么不直接运行呢?

它实际上是 return 2。gcc 版本 4.5.4 与-std=gnu99

于 2012-12-01T10:24:38.657 回答