为什么这个C代码的输出应该是"no"?

Why should the output of this C code be "no"?

我遇到了这个问题。

#include <stdio.h>

int main(void) {
    // your code goes here
    unsigned int i = 23;
    signed char c = -23;

    if (i > c)
        printf("yes");
    else
        printf("no");

    return 0;
}

我无法理解为什么这段代码的输出是 no

有人可以帮助我理解在 C 中 intchar 之间进行比较时比较运算符的工作原理吗?

您正在比较 unsigned intsigned char。这种比较的语义是违反直觉的:大多数涉及 signedunsigned 操作数的二元运算都是在无符号操作数上执行的,在将有符号值转换为无符号值之后(如果两个操作数具有相同的大小晋升)。以下是步骤:

  • signed char 值被提升为具有相同值 -23int
  • 比较intunsigned int,共同的类型是C标准定义的unsigned int
  • int 转换为 unsigned int,值为 UINT_MAX - 23,一个非常大的数字。
  • unsigned int 个值进行比较:23 是较小的值,比较结果为 false。
  • 计算else分支,打印no

更糟糕的是,如果 c 被定义为 long,结果将取决于 longint 是否具有相同的大小或不是。在 Windows 上,它会打印 no,而在 64 位 Linux 上,它会打印 yes.

切勿在比较中混用有符号和无符号值。启用编译器警告以防止此类错误(-Wall-Weverything)。您不妨使用 -Werror 将所有这些警告设为致命警告,以完全避免这种命运多舛的代码。

如需完整参考,请阅读 6.3 Conversions 下 C 标准 (C11) 的以下部分:

  • 整数提升6.3.1.1 布尔值、字符和整数.
  • 中进行了解释
  • 操作数转换详见6.3.1.8 常用算术转换.

您可以从工作组网站下载最新的C11标准草案:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf