C中的比较运算符优化

comparison operator optimization in C

我刚遇到一个有趣的案例,但找不到任何相关信息,我想知道这里是否有人知道答案。

所以我有宏 INT_MAX,它是 int 可以在我的操作系统上存储的最大可能数字。

以下 if 语句有一些奇怪的行为:

#include <stdio.h>
#include <limits.h>

int main(int argc, const char* argv[]) {
    int maxValue = INT_MAX;
    printf("INT_MAX: %d\n", maxValue);
    printf("INT_MAX + 1: %d\n", maxValue + 1);
    
    if (INT_MAX < maxValue + 1) {
        printf("no overflow\n");
    } else {
        printf("overflow\n");
    }
    
    return 0;
}

通过运行这个程序我们得到INT_MAX的值和INT_MAX的溢出,然后是溢出。

如果我用变量 maxValue 切换 INT_MAX,则执行 'else' 并打印“无溢出”。我认为这意味着 if 语句或 < 运算符正在检查传递给它的左右值是否相同,而不是简单地进行实际计算 returns 1 因为它在右侧看到我们正在为同一个变量添加一个正值。

那么这是实际发生的事情还是完全不同的事情?

谢谢!

编辑:INT_MAX 不是 MAX_INT

当计算结果超出结果类型可以表示的范围时,未定义的行为被调用,任何事情都允许发生。

引自N1570 6.5 表达式 5:

If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.

maxValue = INT_MAX的时候maxValue + 1的结果会超出int的范围,所以这里调用了未定义的行为

另一方面,如果您使用无符号整数,计算 UINT_MAX + 1 不会调用 未定义的行为,因为无符号整数计算的结果被定义为对类型范围。

引自 N1570 6.2.5 类型 9:

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

因此,即使将 maxValue < maxValue + 1 替换为 UINT_MAX < maxValue + 1,此代码仍将打印 overflow

#include <stdio.h>
#include <limits.h>

int main(int argc, const char* argv[]) {
    unsigned int maxValue = UINT_MAX;
    printf("UINT_MAX: %u\n", maxValue);
    printf("UINT_MAX + 1: %u\n", maxValue + 1);
    
    if (maxValue < maxValue + 1) {
        printf("no overflow\n");
    } else {
        printf("overflow\n");
    }
    
    return 0;
}

I assume this means that the if statement or < operator is checking if both the left and right values passed to it are the same and instead of doing the actual calculation it simply returns 1 as it sees that on the right hand side we're adding a positive value to the same variable.

So is this what is actually happening or is it something else entirely?

这是编译器通常进行的优化。这很可能是您的示例中发生的事情,尽管证明这种特定的优化是负责任的而不是编译器中的某些其他行为需要深入研究编译器内部。 Godbolt does show that Clang and GCC compile the following code to a constant return value of 1:

int foo(int x)
{
    return x < x+1;
}

Clang 生成的程序集是:

foo:                                    # @foo
        mov     eax, 1
        ret