5 ms·
C integer promotions are what remains of old computers systems which couldn't handle anything but a 'word'. It result in things highly inconsistent on modern 6
by SuchAnonMuchWow 5y ago
C integer promotions are what remains of old computers systems which couldn't handle anything but a 'word'.
It result in things highly inconsistent on modern 64-bit machines:
For example, char/short are automatically promoted to int or unsigned int when an operation is performed on them, but this doesn't happen between int and long.
Simple things like adding two int16_t together to get a int16_t in return is really hard: you need a mask and a extra explicit cast, and you rely on the compiler being smart enough to understand what you are doing and to emit just the instruction you want.
But you don't need to do the same with int32_t, because reasons.
This is a bad default behavior, as it doesn't match either the intuition or underlying hardware, it is inconsistent across all integer types, and to understand why it works that way you need to understand how computers works 30 years ago.
D supporting C integer promotion might be a good thing for portability, but that's it.
- p0nce 5y ago> This is a bad default behavior I don't think so. A lot of existing C code relies on this, and removing the promotion will prime this code to be copy/pasted without fix. Who will rewrite all the C and C++ codecs code out there? A lot of C and C++ programmers actually ignore the int promotion rule, but their code relies on it involuntarily.
- p0nce 5y ago> adding two int16_t together to get a int16_t in return is really hard Because the first thing people will do is: int16_t a, b; a = (int16_t) ((b * 157) >> 12); and then if b * 157 doesn't promote to 32-bit it overflows in the negative and then the code is incorrect.
- dgrunwald 5y agoYou're assuming `int` is 32-bits. The fact that C implicitly promotes to `int` makes it extremely hard to use the stdint.h typedefs without accidentally making platform-specific assumptions. uint16_t a, b, c; a = 50000; b = 40000; c = a * b; This simple code may or may not have undefined behavior depending on the target platform. (it's fine for 16-bit int, UB for 32-bit int, and fine again for 64-bit int) Numeric promotion means that it's almost impossible to write code that is correct on multiple platforms with different sizeof(int).
- p0nce 5y agoWell there is the integer promotion issue, and the integers-have-unknown-size issue.
- flohofwoe 5y agoNot my idea, but: expanding all values used in expressions to "native word size" (e.g. int64_t on modern machines), and only treat "bit width" and "signedness" as load/store attributes doesn't seem like such a bad idea. The problem seems to be that (AFAIK) C stopped at 32-bit integers.
- p0nce 5y agoThe hardware match C, in x86 using 32-bit integers is not slower than using 64-bit integers.
- SuchAnonMuchWow 5y agoI agree, both choices are fine as long as they are consistent. One issue with expanding all values to native word size is that this would manly benefit _very_ old hardware: modern CPUs are as fast directly manipulating any int size as they are manipulating "native word size", or even worse because vector instructions usually manipulate twice many int32 per cycle than they manipulate int64 (and twice many int16 as int32), even if not every code can be vectorized.
- lerno 5y agoIt should be noted that Zig’s int promotion rules are currently broken though.