Comment by dgrunwald
3 hours ago
> ILP64 (wherein int is 64 bits) exists. It's not very popular, but it exists; e.g. ICC supports it.
ILP64 is problematic for existing code: there is lots of stuff like hashcode computations using uint32_t with multiplications, relying on the C standard guaranteeing wraparound for unsigned overflows. But with 64-bit int, uint32_t will promote to a signed int, and overflows will thus be undefined behavior. This problem already exists with uint16_t multiplications on current architectures, but moving the problem to uint32_t will cause trouble for a lot of existing code that thought using fixed-size types like uint32_t would be safe.
Thank you for being one of the few people who understands that in C/C++, `unsigned OP unsigned` can have each operand be promoted to a signed integer and then have the operation overflow and cause undefined behavior.
I chose to deal with this problem by doing a "pointless" operation to force a promotion to at least unsigned int. For example:
This piece of code will work on any machine, such as: (uint16_t = unsigned short = 16 bits, uint32_t = unsigned int = 32 bits); (uint16_t = unsigned short = unsigned int = 16 bits, uint32_t = unsigned long = 32 bits).
But the result is 1, whether you calculate it as 16-by-16 unsigned multiplication (you get 0xFFFE0001 truncated down to 1), or 32-by-32 signed (you multiply -1 by -1 and get 1, with no overflow).
> 32-by-32 signed (you multiply -1 by -1 and get 1, with no overflow)
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.
> stuff like hashcode computations using uint32_t with multiplications, relying on the C standard guaranteeing wraparound for unsigned overflows. But with 64-bit int, uint32_t will promote to a signed int, and overflows will thus be undefined behavior.
Yeah, except that multiplying two 32-bit values, recast as 64-bit signed integers, will not overflow. Even adding another 32-bit value to this product will not overflow. Throw in the final cast to uint32_t to throw away the upper sign bits, and you get the identical result.
> multiplying two 32-bit values, recast as 64-bit signed integers, will not overflow
Factually wrong. Consider: (int64_t)0xFFFFFFFF * (int64_t)0xFFFFFFFF. It definitely overflows.