Home > Software design >  Why the output changes if i put zero instead of the variable?
Why the output changes if i put zero instead of the variable?

Time:06-13

If you use the variable x instead of 0 the output will be Hello. If you use 0 the compiler will display a warning about dividing by zero. The code is below:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int x = 0;
    if (5 < 4 & (7 / x) == 0)
        puts("dividing by zero");
    else
    {
        puts("Hello");
    }
    return 0;
}

CodePudding user response:

5 < 4 is always 0, and 7 / x is an expression without visibile side-effects (defined by the standard as file IO or access to volatile variables, specific implementations may give wider guarantees); as that sub-expression is not required to compute the final result, the compiler is authorized to optimize it out.

The fact that in other contexts (when that operation is actually performed at runtime, or when it's fully known at compile time, as in your question) an equivalent expression may crash the program at runtime or give a compile time warning/error is allowed as well: division by zero is undefined behavior, so the compiler is allowed to do whatever it pleases (including assuming it won't happen when optimizing).

CodePudding user response:

The expression (5 < 4 & (7 / x) == 0) is parsed as

((5 < 4) & ((7 / x) == 0))

The problem is you have undefined behavior whether use x or 0 so anything can happen and the C Standard does not define what the compiler should do. Looking at the compiler output on godbolt.org, the behavior of the program differs for different compiles and different compiler options.

The compiler evaluates (5 & 4) as a constant expression with a value of 0. The right operand ((7 / x) == 0) does not have any observable side effects, besides the undefined behavior in 7 / x which by definition is undefined. If optimisations are enabled, the compiler seems to ignore the potential undefined behavior and determines at compile time that the whole expression has a value of 0. The test is therefore not taken and just the call to puts("Hello"); needs to occur.

If you replace x with its value 0, as the compiler evaluates the whole expression as a constant expression, it cannot ignore the fact that ((7 / 0) == 0) has undefined behavior so it generates a diagnostic, but seems to still ignore the undefined behavior, the whole expression still has a value of 0 so the same puts("Hello") is generated.

Undefined behavior is undefined, so assuming it just produces some value is legitimate and 0 & some_value is 0, which makes the test always take the else branch.

If you disable the optimisations, the code generation changes and the division by 0 either occurs with whatever side effects (a signal is raised on x86 processors) or some other weird side effect occurs (such as the expression becoming always true with clang -O0).

  • Related