Question

Let's say I will only be using types with explicit width, e.g. no int but int32, uint16, etc... is it safe to assume that:

A byte will always take 8 bits and will be 8 bit aligned
A short will always take 16 bits and will be 16 bit aligned
An int will always take 32 bits and will be 32 bit aligned
A long int will always take 64 bits and will be 64 bit aligned
A float will always take 32 bits and will be 32 bit aligned
A double will always take 64 bits and will be 64 bit aligned

--- and also optionally those three will best work if:

A 64bit SIMD datatype will always be 8 byte aligned    
A 128bit SIMD datatype will always be 16 byte aligned
A 256bit SIMD datatype will always be 32 byte aligned

--- and lastly:

A cache page will always be multiple of 32 bytes  // e.g. 32 or 64 bytes

Naturally, I do not imply EVERY hardware platform out there, I am only concerned with x86/x64 and ARM v7/v8

Was it helpful?

Solution

I'd say there is guarantee only if there is a guarantee, and here is what I mean:

typedef qint8
Typedef for signed char. This type is guaranteed to be 8-bit on all platforms supported by Qt.

typedef qint16
Typedef for signed short. This type is guaranteed to be 16-bit on all platforms supported by Qt.

typedef qint32
Typedef for signed int. This type is guaranteed to be 32-bit on all platforms supported by Qt.

typedef qint64
Typedef for long long int (__int64 on Windows). This type is guaranteed to be 64-bit on all platforms supported by Qt.

typedef quint8
Typedef for unsigned char. This type is guaranteed to be 8-bit on all platforms supported by Qt.

typedef quint16
Typedef for unsigned short. This type is guaranteed to be 16-bit on all platforms supported by Qt.

typedef quint32
Typedef for unsigned int. This type is guaranteed to be 32-bit on all platforms supported by Qt.

typedef quint64
Typedef for unsigned long long int (unsigned __int64 on Windows). This type is guaranteed to be 64-bit on all platforms supported by Qt.

This is taken from the Qt documentation. That being said, there are other libraries which guarantee datatype width, for example the Apache Portable Runtime library, which is more streamlined that Qt. Both support x86 and ARM architectures. There are probably others too.

The alignments for SIMD operations seem to be the ones, recommended for optimal performance. The cache line size also seems to be the right one, since x86 processors have 64 byte cache lines, ARM v7 has 32 byte and v8 moves up to 64 bytes as well. So I'd say you are safe as long as you use some kind of library which guarantees width - not the minimum like the standard requires but the absolute width.

OTHER TIPS

At least this assertion

A double will always take 64 bits and will be 64 bit aligned

is false. On Linux/x86, GCC aligns double to only 32-bit boundaries because of historical reasons. (In the 80386 days, it made no sense to align it to a 64-bit boundary because the data bus was only 32-bit wide.)

On Linux/x86-64 this was fixed because when x86-64 was invented aligning double to 64-bit boundaries apparently was beneficial.

It is entirely possible to use pragmas, compiler flags or pointer arithmetic to get into a situation where things are NOT aligned appropriately.

If we restrict your choice to ARM and x86, then your sizes are correct, aside from the fact that MS compilers use long that is 32-bit for hystericalhistorical reasons.

Cache "linesize" is not always 32 bytes. I've worked on older processors with 16-byte cache-alignment. You can be pretty certain that it's always a 2n, and 32 bytes is certainly very common right now.

Edit: Just noticed one of your comments saying you are writing a compiler. I wouldn't worry about it right now (while you are presumably just starting out), but at some point, you may need to consider the __attribute__(packed) or #pragma pack(n) and related bits. There are some datastructures used in for example BMP files that require this sort of packing to deliver the right layout for reading the data directly from a file.

First, using types with explicit widths isn't a good practice. It limits the machines on which your code will run to those which actually support those types (not a great limitation today, but still), and it really doesn't buy you anything.

Second, none of your assumptions will hold. I've known machines with 9 bit bytes, and 36 bit short, int, long and float, and 72 bit double. And machines with 48 bit short, int, long and float, and 96 bit double. And I've heard of machines with 32 bit byte and float.

Of course, if you're only concerned with one or two processors, then you can easily find out what compilers for them do. (Except maybe for alignment: Intel architecture has no alignment constraints, but most compilers enforce them, for performance reasons. And the best alignments for performance have changed, and continue to change, when new versions of the chips appear.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top