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;
}
The logical OR ( || ) operator (logical disjunction) for a set of operands is true if and only if one or more of its operands is true. It is typically used with boolean (logical) values. When it is, it returns a Boolean value.
You can check if a value is either truthy or falsy with the built-in bool() function. According to the Python Documentation, this function: Returns a Boolean value, i.e. one of True or False .
A truth table is a table or chart used to illustrate and determine the truth value of propositions and the validity of their resulting argument. For example, a very basic truth table would simply be the truth value of a proposition p and its negation, or opposite, not p (denoted by the symbol ∼ or ⇁ ).
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With