Dividing by zero in a constant expression Dividing by zero in a constant expression c c

Dividing by zero in a constant expression


Yes, division by zero is undefined behavior and neither the C nor C++ standard impose any requirements in such cases. Although in this case I believe you should at least issue a diagnostic(see below).

Before I go quoting the standards, I should note that although this may be conformant behavior quality of implementation is a different issue, being merely conforming is not the same as being useful. As far as I know the gcc, clang, Visual Studio and Intel(as per tpg2114) team consider internal compiler errors(ICEs) to be bugs that should be reported. It should be noted that both current gcc and clang produce a warning for this case seemingly regardless of flags provided. In the case where both operands are literals/constants, the case we have here, it seems rather straight forward to detect and provide a diagnostic for this. clang produces the following diagnostic for this case (see it live):

warning: division by zero is undefined [-Wdivision-by-zero]int x = 1 / 0 ;          ^ ~

From the draft C11 standard section 6.5.5 Multiplicative operators (emphasis mine):

The result of the / operator is the quotient from the division of the first operand by the second; [...] if the value of the second operand is zero, the behavior is undefined.

and so it is undefined behavior.

The draft C++ standard section 5.6 [expr.mul] says:

The binary / operator yields the quotient [...] If the second operand of / or % is zero the behavior is undefined [...]

again undefined behavior.

Both the draft C++ standard and draft C standard have a similar definition for undefined behavior both saying:

[...]for which this International Standard imposes no requirements

The phrase imposes no requirements seems too allow any behavior, including nasal demons. Both have a similar note saying something along the lines of:

Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

So although notes are not normative, it seems like if you are going to terminate during translation, you should at least issue a diagnostic. The term terminating is not defined, so it is hard to argue what this allows. I don't think I have seen a case where clang and gcc have an ICE without a diagnostic.

Does the code have to be executed?

If we read Can code that will never be executed invoke undefined behavior? we can see at least in case of C there is room for debate where the 1 / 0 has to be executed in order to invoke undefined behavior. What is worse in the C++ case the definition of behavior is not present so part of the analysis used for the C case can not be used for the C++ case.

It seems that if the compiler can prove the code will never be executed then we can reason that it would be as-if the program did not have undefined behavior but I don't think this is provable, just reasonable behavior.

From the C perspective WG14 defect report 109 further clarifies this. The following code example is given:

int foo(){  int i;  i = (p1 > p2); /* Must this be "successfully translated"? */  1/0; /* Must this be "successfully translated"? */  return 0;} 

and the response included:

Furthermore, if every possible execution of a given program would result in undefined behavior, the given program is not strictly conforming.
A conforming implementation must not fail to translate a strictly conforming program simply because some possible execution of that program would result in undefined behavior. Because foo might never be called, the example given must be successfully translated by a conforming implementation.

So in the case of C, unless it can be guaranteed that the code invoking undefined behavior will be executed then the compiler must successfully translate the program.

C++ constexpr case

If x was a constexpr variable:

constexpr int x = 1 / 0 ;

it would be ill-formed and gcc produces a warning and clang makes it error (see it live):

error: constexpr variable 'x' must be initialized by a constant expressionconstexpr int x = 1/ 0 ;             ^   ~~~~note: division by zeroconstexpr int x = 1/ 0 ;                  ^warning: division by zero is undefined [-Wdivision-by-zero]constexpr int x = 1/ 0 ;                  ^ ~

Helpfully noting that division by zero is undefined.

The draft C++ standard section 5.19 Constant expressions [expr.const] says:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions

and includes the following bullet:

an operation that would have undefined behavior [Note: including, for example, signed integer overflow (Clause 5), certain pointer arithmetic (5.7), division by zero (5.6), or certain shift operations (5.8) —end note ];

Is 1 / 0 a constant expression in C11

1 / 0 is not a constant expression in C11, we can see this from section 6.6 Constant expressions which says:

Each constant expression shall evaluate to a constant that is in the range of representable values for its type.

although, it does allow:

An implementation may accept other forms of constant expressions.

So 1 / 0 is not a constant expression in either C or C++ but that does not change the answer since it is not being used in a context that requires a constant expression. I suspect the OP meant that 1 / 0 is available for constant folding since both operands are literals, this would also explain the crash.


The mere presence of 1 / 0 does not permit the compiler to crash. At most, it is permitted to assume that the expression will never be evaluated, and thus, that execution will never reach the given line.

If the expression is guaranteed to be evaluated, the standard imposes no requirements on the program or compiler. Then the compiler can crash.

1 / 0 is only UB if evaluated.

The C11 standard gives an explicit example of 1 / 0 being defined behavior when unevaluated:

Thus, in the following initialization,

        static int i = 2 || 1 / 0;

the expression is a valid integer constant expression with value one.

Section 6.6, footnote 118.

1 / 0 is not a constant expression.

Section 6.6 of the C11 standard, under Constraints, says

  1. Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.
  2. Each constant expression shall evaluate to a constant that is in the range of representable values for its type.

Since 1/0 does not evaluate to a constant in the range of values representable by an int, 1/0 is not a constant expression. This is a rule about what counts as a constant expression, like the rule about not having assignments in it. You can see that at least for C++, Clang doesn't consider 1/0 a constant expression:

prog.cc:3:18: error: constexpr variable 'x' must be initialized by a constant expression   constexpr int x = 1/ 0 ;                 ^   ~~~~

It wouldn't make much sense for an unevaluated 1 / 0 to be UB.

(x == 0) ? x : 1 / x is perfectly well-defined, even if x is 0 and evaluating 1/x is UB. If it were the case that (0 == 0) ? 0 : 1 / 0 were UB, that would be nonsense.


From C standard draft (N1570):

6.5.5 Multiplicative operators

...

  1. The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

And about undefined behaviour in chapter 3. Terms, definitions, and symbols:

3.4.3

  1. undefined behavior
    behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
  2. NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

So crashing the compiler is allowed.