I'm using SSE/AVX and I need to store aligned data. how ever, my data can be of different types. so I use a union like this
union Data
{
bool Bools[128];
int32 Ints32[128];
int64 Ints64[128];
// ... other data types
} data;
Can I do the following?
union alignas(16) Data
{
alignas(4) bool Bools[128];
alignas(4) int32 Ints32[128];
alignas(8) int64 Ints64[128];
alignas(16) Bar Bars[128]; // Bar is 16 bytes
} data;
so I expect Ints32 and Bool elements to be aligned as 4 bytes, yet Int64 elements are aligned as 8 bytes.
because of Bar first element of each array (or basically &data) should also be aligned to 16 bytes. but elements of each array should be aligned as stated. so is my union correct?
The alignment specifier applies only to the entity it defines. It applies to the whole class (union) object's alignment or the alignment of the individual arrays. It never applies to elements of the array.
The alignment of elements in an array of type T can never be guaranteed to be stricter than the size of T, because elements of an array must be allocated contiguously in memory without padding. This is for example necessary so that pointer arithmetic can work. The type of the member doesn't include any information about the alignment specifier you used, so e.g. evaluating Bools[i] must be sure how far apart individual elements of type bool and can't adjust to alignment specifiers.
If you want to adjust element-wise alignment then you need to specify your own type with the required alignment and form an array of that type.
Because the initial address of the subobjects of a union has to be equal to that of the union object itself, there is also no point to add weaker alignment specifiers to the subobjects. They can't have any effect.
Related
The question is more of theory-based than practical implementation.
What I would like to know is, in the code:
struct temp {
int num;
struct temp *next;
};
In the structure made above, how does the compiler decide how much of space should be allocated in memory when we instantiate it?
If I try to dry-run the code, the size of an integer would be 2 or 4 bytes, after that, if I try to find the size of the pointer to the structure itself, I enter a structure containing another integer and a pointer to itself.
By this logic, the compiler would enter an infinite loop when deciding to allocate space to an element of this structure, how then is the space decided?
P.S. I did try to find out the size of this structure myself (using the sizeof() operator, it turned out to be 16 bytes (the size of the integer being 4 bytes)... I'm interested in knowing how did it determine this figure of 16 bytes as the space required!
A structure containing a pointer to itself is not a problem.
A pointer has a fixed size, so it doesn't matter how big the size of the structure it points to is. On most systems you're likely to come across, a pointer will be either 4 bytes or 8 bytes in size.
For the struct you've given, the int field will probably use 4 bytes and the struct temp * field will probably use 8 bytes. This means the struct will be at least 12 bytes in size, probably 16 due to padding for proper alignment.
If on the other hand you had something like this:
struct temp {
int num;
struct temp next;
};
This would not be legal because the struct contains a copy of itself, which would in turn contain a copy of itself, and so on.
In the structure made above, how does the compiler decide how much of space should be allocated in memory when we instantiate it?
Pointer types take up a fixed size, which is not dependent on the pointed-to type (IOW, the size and representation of struct temp * is not in any way dependent on the size or representation of struct temp). Furthermore, all pointer to struct types have the same size:
6.2.5 Types
...
28 A pointer to void shall have the same representation and alignment requirements as a
pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of
compatible types shall have the same representation and alignment requirements. All
pointers to structure types shall have the same representation and alignment requirements
as each other. All pointers to union types shall have the same representation and
alignment requirements as each other. Pointers to other types need not have the same
representation or alignment requirements.
C 2011 online draft
On platforms like x86, all pointer types have the same size and representation, but the standard has to take oddball architectures into account.
It's no different than if you had a pointer to int or pointer to void as a member. The only thing that makes it look weird is that you're creating a self-referential pointer, which is allowed:
6.7.2.1 Structure and union specifiers
...
3 A structure or union shall not contain a member with incomplete or function type (hence,
a structure shall not contain an instance of itself, but may contain a pointer to an instance
of itself), except that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union containing, possibly
recursively, a member that is such a structure) shall not be a member of a structure or an
element of an array.
ibid.
Even though the struct type itself is not complete until the closing } of the definition, any pointer to it is complete (that is, its size is known).
The size of the pointed-to type matters for pointer arithmetic (i.e., the address value resulting from p + 1 will depend on the size of the thing p points to). However, it doesn't matter for storing the pointer itself.
I was looking at a small program -
#include<iostream>
class A
{
bool a;
bool c;
};
int main()
{
std::cout << sizeof(A) << std::endl;
return 0;
}
Here, it shows the size of class A as 2 bytes. But, if I add another integer data member to this class as -
class A
{
int b;
bool a;
bool c;
};
Now, it shows the size of class A as 8 bytes instead of 6 bytes. Why compiler does padding in second case & why not in first case?
The size of a structure is a multiple of the alignment requirement of a data member with the largest alignment requirement. This is so that when an array of structures is used there is no padding between the elements of the array and the alignment requirements for each data member of the structure is satisfied.
In the first case, the largest alignment requirement is alignof(bool) which is 1, so the size of the structure is a multiple of 1.
In the second case, the largest alignment requirement is alignof(int) which is 4, so the size of the structure is a multiple of 4.
Try adding a double member with the alignment requirement of 8.
A rule of thumb to minimize padding in structures is to arrange data members from the largest alignment requirement to the smallest, e.g. doubles followed by pointers followed by longs followed by ints followed by shorts followed by bools followed by chars.
Imagine you have an Array of As. The second A in the array would have its member b misaligned if there was no additional padding. That said the compiler can choose whatever it feels like. Misaligned accesses cost runtime, padding costs space. Your compiler favored runtime.
The only things the compiler must do is align the first member so that the address of that member is the same as the address of the structure and preserve the order of the members as specified by the class.
Other than these, the compiler is free to do what it wants (unless you tell it otherwise using packing directives which vary from compiler to compiler). It will probably pack members in order to optimise runtime speed.
Suppose I have some type T that has to be N bytes aligned. Now I declare an array of type T:
T array[size];
Will the array have the same alignment requirements as type T or will it have any other alignment requirements?
Yes, the alignment requirements must be the same. Obviously an array of T must be aligned at least as strictly as a single T otherwise its first member would not be properly aligned. The fact that an array cannot be more strictly aligned than its element type follows from the standard section 8.3.4 which says that arrays are contiguously allocated element subobjects. Consider this array of arrays:
T a[2][size];
Whatever the value of size, there can be no "extra" padding between the two arrays a[0] and a[1] otherwise this violates the contiguosly allocated requirement.
Equivalently, we know that (char*)&a[1] == (char*)&a[0] + sizeof(a[0]) and sizeof(a[0]) == sizeof(T[size]) == size * sizeof(T). As this holds for any size it must be possible to place an array of T at any address which is suitably aligned for a single T object (given adequate address space).
The array's alignment requirements will be identical to those of the array elements, I believe.
Obviously, the start of the array must be aligned at least as strictly as its first element requires, so its alignment requirements can't be less strict.
The start address of the array plus the size of each element must leave the second element sufficiently aligned. That places a constraint on the size of the element type, which I believe means padding can be introduced at the end of a structure just to keep arrays aligned, even if you never use that struct in an array. But it does not mean there's any need for stricter alignment.
By induction, subsequent elements are OK if the first two are OK, so giving the array the same alignment requirements as its elements should be fine.
A citation from the spec would be nice, though.
The rules are the same i believe but the interpretation might be confusing.
I believed since each element of array would be of the same size so only aligning the first element would automatically align the rest and hence there would never be any padding between elements.
This might be true in case of a trivial array but not for complex scenarios.
The stride of an array can be large than element size i.e. there could be pads between each individual elements.
Following is a good example
struct ThreeBytesWide {
char a[3];
};
struct ThreeBytesWide myArray[100];
source - stride wikipedia
Each element of ThreeBytesWide array could be aligned to four byte boundary
Edit: As elaborated in the comments, the mention of having pads between individual elements is when the element itself is say 3 bytes and aligned to four byte boundary.
An array of objects is required to be contiguous, so there's never padding between the objects, though padding can be added to the end of an object (producing nearly the same effect).
C++ Data Member Alignment and Array Packing
#include <iostream>
__declspec(align(32))
struct Str1
{
int a;
char c;
};
template<typename T>
struct size
{
T arr[10];
};
int main()
{
size<Str1> b1;
std::cout << sizeof(Str1) << std::endl; // prints 32
std::cout << sizeof(b1) << std::endl; // prints 320
std::cin.ignore();
return 0;
}
References:
Data alignment in C++, standard and portability
http://msdn.microsoft.com/en-us/library/83ythb65.aspx
I have a structure where the members have certain alignment requirements while no such requirement exist for the structure itself.
I'm using gcc so using __attribute__((aligned(n))) will do the trick, unless (as far as I know) an instance of the struct is allocated on the heap.
How do I keep the alignment for heap allocated instances? posix_memalign(3) will align the structure itself, but not the structure members, so I can't see how to make it work with that function.
The source is here: https://github.com/colding/disruptorC/blob/master/src/disruptor.h#L92
No matter where a struct is—stack or heap—the layout of the struct must be the same. The compiler ensures that the sizeof() and the layout of elements within the struct match the alignment requirements (via padding). It also gives the struct itself a required alignment so that its members end up on the right boundary (this value is the largest alignment of any of its members).
So just use posix_memalign and you'll be fine:
MyStruct* ptr;
posix_memalign(&ptr, alignof(MyStruct), sizeof(MyStruct));
For example, if you have this definition:
struct MyStruct {
char c;
double d;
}
It's compiler-dependent, of course, but the most likely behavior is that the compiler lays out the following:
1-byte char
7 bytes of padding
8-byte double
and gives the whole thing an alignment of 8 bytes. Then, if the struct itself is aligned properly (on an 8-byte boundary), the double that's 8 bytes offset into it will also be properly aligned.
(alignof is different in different compilers/standards: __alignof__ in gcc, __alignof in MSVC, and alignof in C11/C++11.)
suppose a struct defined like this:
struct S{
char a[3];
char b[3];
char c[3];
};
then what will be the output of printf("%d", sizeof(S)) ? On My compiler of Vc++ 2008 expression, the output is 9. And I got confused... I suppose the result be 12, but it is not. Shouldn't the compiler align the structure to 4 or 8 ?
The value of the sizeof-expression is implementation-dependent; the only thing guaranteed by the C++ standard is that it must be at least nine since you're storing nine char's in the struct.
The new C++11 standard has an alignas keyword, but this may not be implemented in VC++08. Check your compiler's manual (see e.g. __declspec(align(#))).
There's nothing in S that would force any of its members to be aligned other than per-byte so the compiler doesn't need to add any padding at all.
First, the alignment is implementation dependent, so it will depend on the compiler.
Now, remember that for a statically allocated array, the size need not be stored (the standard does not require it is), therefore it is usual for the alignment of an array to be the alignment of its elements.
Here, char[3] thus has an alignment of 1, and they are perfectly packed.
There is a compiler switch, /Zp, that allows you to set the default struct member alignment. There are also some other methods for specifying alignment in the c language.
Check out this MSDN post for details:
http://msdn.microsoft.com/en-us/library/xh3e3fd0(v=vs.80).aspx
Maybe your compiler is using one of these settings?
The typical requirement that each member be aligned only requires that the structure itself be aligned to the largest member type. Since all member types are char, the alignment is 1, so there's no need for padding. (For arrays, the base type (all extents removed) is what counts.)
Think about making an array of your structure: You'll want all the members of all the elements of that array to be aligned. But in your case that's just one large array of chars, so there's no need for padding.
As an example, suppose that on your platform sizeof(short) == 2 and that alignment equals size, and consider struct X { char a; short b; char c; };. Then there's one byte internal padding between a and b to align b correctly, but also one byte terminal padding after c so that the entire struct has a size that's a multiple of 2, the largest member size. That way, when you have an array X arr[10], all the elements of arr will be properly aligned individually.
The compiler is given fairly wide latitude about how its aligns data. As a practical matter, however, the alignment of a datum will not exceed its size. That is, chars must be byte-aligned, while ints and longs are often four-byte aligned.
Additionally, structs are aligned to the strictest alignment requirement of their members.
So, in your example, the strictest internal alignment requirement is 1-byte aligned, so the struct is 1-byte aligned. This means that it requires no padding.