chux chux - 23 days ago 6
C Question

When an `int` at max value and tested with with postfix ++, is code well-defined?


EXAMPLE An example of undefined behavior is the behavior on integer overflow. C11dr §3.4.3 3


int
overflow is undefined behavior, but does that apply to the following which exists the loop, and does not use the the side effect of the now out-of-scope
i
? In particular, does this Postfix increment spec help?


... The value computation of the result is sequenced before the side effect of
updating the stored value of the operand. ... §6.5.2.4 2


Compiles without warnings with well-enabled C11

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

int main(void) {
// Specified behavior when `i` has the value `INT_MAX`?
for (int i = INT_MAX - 2; i++ < INT_MAX;) {
printf("%d\n", i);
}
puts("Done");
return 0;
}


Sample output

2147483646
2147483647
Done


Of course code can be re-written to avoid this quandary with the below. Still, looking for confirmation concerning the above. (I think it is UB.) A similar issue exists with
INT_MIN
and
i--
.

for (int i = INT_MAX - 2; i < INT_MAX;) {
i++;
printf("%d\n", i);
}





GNU C11 (GCC) version 5.3.0 (i686-pc-cygwin)
compiled by GNU C version 5.3.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
'-std=c11' '-O0' '-g3' '-Wpedantic' '-Wall' '-Wextra' '-Wconversion' '-c' '-fmessage-length=0' '-v' '-MMD' '-MP' '-MF' xx.o' '-o' 'xx.o' '-mtune=generic' '-march=i686'
/usr/lib/gcc/i686-pc-cygwin/5.3.0/cc1.exe -quiet -v -MMD xx.d -MF xx.d -MP -MT xx.o -dD -Dunix -idirafter ... xx.c

Answer

Regardless of the scope i, the program has undefined behaviour in the evaluaton of i++ when i is 2147483647 (assuming INT_MAX=2147483647 on your system).

Your example can be re-written as:

include <limits.h>

int main(void) {
  // Specified behavior when `i` has the value `INT_MAX`?
  {
      int i = INT_MAX;
      i++;
  }
  puts("Done");
  return 0;
}

The value computation of i++ results in integer overflow irrespective of whether the computed value is used or if that object cease to exist right after the next sequence point; sequence point or storage duration of the object is irrelevant whether there's an undefined behaviour here.

Comments