If you use GCC 11.2.0 and the -Wall -O2
options, you will see a warning about undefined behavior:
test.cpp: In function 'int f(int)':
test.cpp:7:42: warning: iteration 5 invokes undefined behavior [-Waggressive-loop-optimizations]
7 | int64_t time = 4500000000 + (i) * 500000000;
| ~~~~^~~~~~~~~~~
test.cpp:5:27: note: within this loop
5 | for (int32_t i = 0; i < 10; ++i)
| ~~^~~~
The compiler knows that 5 * 500000000 is too large to fit in an int
(which is typically 32-bit). Signed integer overflow is undefined behavior in C++. Therefore, the compiler is free to assume that this overflow never happens, so it will assume that i
can never reach 10, so it can get rid of the part of your for loop that checks i < 10
. I know that sounds crazy, but if your program does undefined behavior, the compiler is free to do whatever it wants.
Just add some casts to specify that you want to do 64-bit arithmetic. This eliminates the warnings, the overflows, and the undefined behavior:
int64_t time = (int64_t)4500000000 + i * (int64_t)500000000;
Update: For a larger project that could have more bugs, you might consider using GCC's -fwrapv
option, which makes the behavior of signed integer overflow be defined. You could also use -fsanitize=signed-integer-overflow
or -fsanitize=undefined
to detect these issues at run time, if your toolchain supports those options.