Reputation: 2100
According to this answer:
The minimal alignment is (on a given platform) the one which won't give crashes.
With GCC 8, there are two functions to get the minimal and the preferred alignment:
alignof
operator that gives the minimum alignment__alignof__
function that gives the preferred alignmentFor a double
, the minimum alignment is 4 bytes and the preferred alignment is 8 bytes on i386 architectures. Therefore, if I correctly understood the answer I quoted above, an application that store a double
at an address that is not a multiple of 4, the program should crashes.
Let's look at the following code:
#include <iostream>
void f(void* ptr) {
double* ptr_double = (double*) ptr;
ptr_double[0] = 3.5;
std::cout << ptr_double[0] << std::endl;
std::cout << &ptr_double[0] << std::endl;
}
int main()
{
alignas(__alignof__(double)) char arr[9];
f(arr+1);
return 0;
}
However, if I compile it with -m32
option, it runs well and I get the following results:
3.5
0xffe41571
We can see my double
is misaligned but the program runs without any problem.
The very next sentence of the quote above is:
On x86-64 it is one byte.
In some ways, it seems to be true because my code works. But, in this case, why alignof
returns 4?
Where is the problem, here? Is the given definition of the minimum alignment is wrong? Or is there something I don't get?
Upvotes: 0
Views: 174
Reputation: 238421
The minimal alignment is (on a given platform) the one which won't give crashes.
Therefore, if I correctly understood the answer I quoted above, an application that store a double at an address that is not a multiple of 4, the program should crashes.
You are denying the antecedent.
Just because conforming to alignment doesn't give crashes, does not mean that misalignment will give crashes.
This is what the C++ standard says:
[expr.alignof] An alignof expression yields the alignment requirement of its operand type.
[basic.align] Object types have alignment requirements ([basic.fundamental], [basic.compound]) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier.
As far as the C++ language is concerned, there are no misaligned objects, so it doesn't specify anything about their behaviour. What you're doing is accessing a non-existing object, and the behaviour of the program is undefined.
Some CPU architectures, and in particular the one that you're using1, do not crash when using misaligned memory addresses. Such operations are simply more or less slower.
But, in this case, why alignof returns 4?
Because the language implementation chose so. Presumably because it is faster than using 1 or 2, but not faster than using 8.
1 This is what the programmers reference manual of 80386 says:
Note that words need not be aligned at even-numbered addresses and doublewords need not be aligned at addresses evenly divisible by four. This allows maximum flexibility in data structures (e.g., records containing mixed byte, word, and doubleword items) and efficiency in memory utilization. When used in a configuration with a 32-bit bus, actual transfers of data between processor and memory take place in units of doublewords beginning at addresses evenly divisible by four; however, the processor converts requests for misaligned words or doublewords into the appropriate sequences of requests acceptable to the memory interface. Such misaligned data transfers reduce performance by requiring extra memory cycles. For maximum performance, data structures (including stacks) should be designed in such a way that, whenever possible, word operands are aligned at even addresses and doubleword operands are aligned at addresses evenly divisible by four. Due to instruction prefetching and queuing within the CPU, there is no requirement for instructions to be aligned on word or doubleword boundaries. (However, a slight increase in speed results if the target addresses of control transfers are evenly divisible by four.)
However, the successor architectures of i386 have introduced vector extensions which do require alignment.
In conclusion: GCC documentation has different definition for what "minimum alignment" means than Starynkevitch has.
Upvotes: 5