Is there a more-or-less reliable way (not necessarily perfect) to detect the machine word size of the target architecture for which I'm compiling?
By machine word size I mean the size of the integer accumulator register (e.g. EAX on x86, RAX on x86_64 etc., not streaming extensions, segment or floating-point registers).
The standard does not seem to provide a "machine word" data type. So I'm not looking for a 100% portable way, just something that works in most common cases (Intel x86 Pentium+, ARM, MIPS, PPC - that is, register-based, contemporary commodity processors).
size_t
and uintptr_t
sound like good candidates (and in practice matched the register size everywhere I tested) but are of course something else and are thus not guaranteed to always do so as is already described in Is size_t the word size.
Context
Let's assume I'm implementing a hashing loop over a block of contiguous data. It is OK to have the resulting hash depend on the compiler, only speed matters.
Example: http://rextester.com/VSANH87912
Testing on Windows shows that hashing in chunks of 64 bits is faster in 64-bit mode and in 32 bits in 32-bit mode:
64-bit mode
int64: 55 ms
int32: 111 ms
32-bit mode
int64: 252 ms
int32: 158 ms
That being said, on Windows with Intel processors, the nominal word size will be either 32 or 64 bits and you can easily figure this out: if your program is compiled for 32-bits, then the nominal word size is 32-bits. if you have compiled a 64-bit program then then the nominal word size is 64-bits.
DWORD (32 bits/4 bytes) QWORD (64 bits/8 bytes)
Yes, quite often int will be the same as the size of a register in the processor, but most 64-bit processors do not follow this rule, as it makes data unnecessarily large.
Because the C and C++ languages deliberately abstract away such considerations as the machine word size, it's unlikely that any method will be 100% reliable. However, there are the various int_fastXX_t
types that may help you infer the size. For example, this simple C++ program:
#include <iostream>
#include <cstdint>
#define SHOW(x) std::cout << # x " = " << x << '\n'
int main()
{
SHOW(sizeof(int_fast8_t));
SHOW(sizeof(int_fast16_t));
SHOW(sizeof(int_fast32_t));
SHOW(sizeof(int_fast64_t));
}
produces this result using gcc version 5.3.1 on my 64-bit Linux machine:
sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 8
sizeof(int_fast32_t) = 8
sizeof(int_fast64_t) = 8
This suggests that one means to discover the register size might be to look for the largest difference between a required size (e.g. 2 bytes for a 16-bit value) and the corresponding int_fastXX_t
size and using the size of the int_fastXX_t
as the register size.
Windows 7, gcc 4.9.3 under Cygwin on 64-bit machine: same as above
Windows 7, Visual Studio 2013 (v 12.0) on 64-bit machine:
sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 4
sizeof(int_fast32_t) = 4
sizeof(int_fast64_t) = 8
Linux, gcc 4.6.3 on 32-bit ARM and also Linux, gcc 5.3.1 on 32-bit Atom:
sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 4
sizeof(int_fast32_t) = 4
sizeof(int_fast64_t) = 8
I think you want
sizeof(size_t)
which is supposed to be the size of an index. ie. ar[index]
32 bit machine
char 1
int 4
long 4
long long 8
size_t 4
64 bit machine
char 1
int 4
long 8
long long 8
size_t 8
It may be more complicated because 32 bit compilers run on 64 bit machines. Their output 32 even though the machine is capable of more.
I added windows compilers below
Visual Studio 2012 compiled win32
char 1
int 4
long 4
long long 8
size_t 4
Visual Studio 2012 compiled x64
char 1
int 4
long 4
long long 8
size_t 8
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