Wrong. You mentally casted each operand to int16_t before subsequently casting to int32_t. The first step is unjustified.
The correct calculation according to the C standard is: (int32_t)0xFFFF * (int32_t)0xFFFF, which definitely overflows.
Wrong. You mentally casted each operand to int16_t before subsequently casting to int32_t. The first step is unjustified.
The correct calculation according to the C standard is: (int32_t)0xFFFF * (int32_t)0xFFFF, which definitely overflows.
That's horrifying. Why were unsigned shorts made to convert to signed ints by zero-extension, again?
> Integer promotion is the implicit conversion of a value of any integer type with rank less or equal to rank of int or of {a bit-field of type _Bool(until C23)/bool(since C23), int, signed int, unsigned int}, to the value of type int or unsigned int.
> If int can represent the entire range of values of the original type (or the range of values of the original bit-field), the value is converted to type int. Otherwise the value is converted to unsigned int.
The fact that the C/C++ integer conversion rules have these unintuitive footguns is why I made it a talking point.
Makes me wonder how ergonomic would a language with actually correct signatures for the arithmetic operators be.
+<S, M, N>: int<S, M> × int<S, N> → int<S, max(M, N)+1> // alternatively int<S, max(M, N)> × bool
-<S, M, N>: int<S, M> × int<S, N> → int<signed, max(M, N)+1> // alternatively int<signed, max(M, N)> × bool
*<S, M, N>: int<S, M> × int<S, N> → int<S, M+N>
/<S, M, N>: int<S, M> × int<S, N> → int<S, M>
%<S, M, N>: int<S, M> × int<S, N> → int<S, N>