iTranslated by AI
Signed Integers in C Are Not Modular Arithmetic
It is sometimes explained that addition, subtraction, and multiplication of signed integers in C are "modular arithmetic modulo
Here are two examples where this difference can be observed.
First, let's look at unary minus. Consider the following program:
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
bool f(int x)
{
return x == -x;
}
int main()
{
printf("%s\n", f(INT_MIN) ? "true" : "false");
}
If unary minus for the int type were performed using modular arithmetic modulo x for which f returns true: 0 and INT_MIN. However, since overflow of unary minus for int is actually undefined behavior, the compiler can perform optimizations without considering the case where x = INT_MIN.
In fact, with Clang, the execution result of the above program changes depending on whether optimization is enabled:
$ clang -o test1 test1.c
$ ./test1
true
$ clang -o test1 -O2 test1.c
$ ./test1
false
(The fact that the behavior of x == -x changes due to compiler optimization was something the author of LuaJIT pointed out to me when I opened an issue: Undefined behavior with negation of INT*_MIN · Issue #928 · LuaJIT/LuaJIT)
As another example, consider the following program involving multiplication:
#include <stdbool.h>
#include <stdio.h>
bool g(int x)
{
return x * x >= 0;
}
int main()
{
printf("%s\n", g(65535) ? "true" : "false");
}
Assume that the width of int is 32 bits. If multiplication for the int type were performed using modular arithmetic modulo x = 65535, x * x would be -131071. However, since overflow of int multiplication is actually undefined behavior, the compiler can perform optimizations without considering overflow.
In fact, with Clang, the execution result of the above program changes depending on whether optimization is enabled:
$ clang -o test2 test2.c
$ ./test2
false
$ clang -o test2 -O2 test2.c
$ ./test2
true
Note that for unsigned integers in C, addition, subtraction, and multiplication are guaranteed to be performed as modular arithmetic modulo
Finally, the version of the compiler I used for verification is as follows:
$ clang --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Discussion