Вопрос

I'm currently learning C program But I came across some weird behavior I expected one result but two results is printed like this

$ ./a.out
yes1 0x80000000
yes3 0x80000000

How could possible that?
I can't understand the result.

OS : x86_64 Ubuntu Linux
C compiler : gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1

gcc -O2 weird.c

#include <stdio.h>

int main() {

    int i = 0x7fffffff;
    int ii = 0x0000000f;

    if ((i + 1) < ii)
        printf ("yes1 %#x\n", i + 1);

    if ((i + 1) == ii)
        printf ("yes2 %#x\n", i + 1);

    if ((i + 1) > ii)
        printf ("yes3 %#x\n", i + 1);

    return 0;
}
Это было полезно?

Решение

In your case (i+1) is overflowing over the range of the integer variable.

The truth is that overflow on a signed int variable is an undefined behaviour in ANSI standard, so strictly speaking it may lead to any result. Your compiler may be conform to the standard but anyone with good computer understanding would expect that the variable will overflow to negative values simply because computer registers do not distinct signed/unsigned ranges.

Here is what ANSI standard says on Undefined behavior (among other cases):

The behavior in the following circumstances is undefined:

An arithmetic operation is invalid (such as division or modulus by 0) or produces a result that cannot be represented in the space provided (such as overflow or underflow) ($3.3).

On the other side, this is not valid for unsigned types:

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 unsigned integer type.

Also here is the related part from referred section ($3.3 Expressions):

If an exception occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not representable), the behavior is undefined.

Другие советы

In all the cases in your code i+1 is producing signed integer overflow which is undefined behavior, which means the program can behave unpredictably. We can see it is undefined from the draft C99 standard section 6.5 Expressions paragraph 5 which says(emphasis mine):

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.

It is the same section in the draft C11 standard as well.

One possible way to have caught this would be use clangs -fsanitize=undefined option which is part clangs santizer suite we get the following runtime errors:

runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'

I think you're running into an optimizer case where the compiler is saying that for integers, x+1>y can be computed more efficiently as x>=y... and unfortunately while that's generally true, and is always true for unsigned values, this one specific case where x+1 wraps around to be negative breaks the assumption.

However, since signed int overflow gets us into the realm of undefined behavior (see @Marian's answer), this is not incorrect. Just surprising.

(Thought about deleting my answer, but since it illustrates how both tests could be true I think it's worth keeping.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top