Let's say that we have uint_least8_t var
, where, hypothetically speaking, var
won't possibly ever exceed the value 255.
I know that's not how programming works and "possibly" and "ever" are a blasphemy, but, aside from complicating the code and making it less readable, what makes always using fixed width integers a bad idea?
Compatibility with other code, and not imposing arbitrary restrictions.
A large portion of the integer variables you use in a typical C program are array indices, object counts, etc. Such values are inherently not representable as fixed-width integer types whose width is known at the time of writing the program; the possible range varies by implementation. (This is related to the fact that a given C implementation is not Turing-equivalent; only an infinite family of implementations, via the Transdichotomous model is). Cetainly you could decide that you only want to support up to 2^32 (for example) of a given thing, and thereby get by with using a fixed-width type, but it's anti-idiomatic, and such code won't be compatible with typical (including std lib) interfaces that use size_t
and might be passing or accepting larger objects.
Performance is another reason.
Narrow operands require additional narrowing/widening instructions. This can't always be optimized away without side effects. And sometimes the optimizer just isn't smart enough and plays it safe.
Take the following contrived example.
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono_literals;
int main()
{
auto tm1 = chrono::high_resolution_clock::now();
unsigned int n = 0;
unsigned int x = 0; // though, uint8_t would have been enough!
for (unsigned int i = 0; i < 1000000000; i++) {
n += (x * i);
x = (n + 1) & 0x7F;
}
auto tm2 = chrono::high_resolution_clock::now();
cout << n << ", " << (tm2 - tm1) / 1.0s << " s" << endl;
}
If we change the type of x
from unsigned int
to uint8_t
, the application becomes 15% slower (2s instead of 1.7s run time on x86-64 when compiled with GCC 7.2 -O3
full optimization on).
Assembly with a 32-bit x
:
.L2:
imul eax, edx
inc edx
add ebx, eax
lea eax, [rbx+1]
and eax, 127
cmp edx, 1000000000
jne .L2
Assembly with an 8-bit x
:
.L2:
movzx eax, al ; owww!
imul eax, edx
inc edx
add ebp, eax
lea eax, [rbp+1]
and eax, 127
cmp edx, 1000000000
jne .L2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With