According to MSDN, the /Zp command defaults to 8, which means 64-bit alignment boundaries are used. I have always assumed that for 32-bit applications, the MSVC compiler will use 32-bit boundaries. For example:
struct Test
{
char foo;
int bar;
};
The compiler will pad it like so:
struct Test
{
char foo;
char padding[3];
int bar;
};
So, since /Zp8 is used by default, does that mean my padding becomes 7+4 bytes using the same example above:
struct Test
{
char foo;
char padding1[7];
int bar;
char padding2[4];
}; // Structure has 16 bytes, ending on an 8-byte boundary
This is a bit ridiculous isn't it? Am I misunderstanding? Why is such a large padding used, it seems like a waste of space. Most types on a 32-bit system aren't even going to use 64-bits, so the majority of variables would have padding (probably over 80%).
That's not how it works. Members are aligned to a multiple of their size. Char to 1 byte, short to 2, int to 4, double to 8. The structure is padded at the end to ensure the members still align correctly when the struct is used in an array.
A packing of 8 means it stops trying to align members that are larger than 8. Which is a practical limit, the memory allocator doesn't return addresses aligned better than 8. And double is brutally expensive if it isn't aligned properly and ends up straddling a cache line. But otherwise a headache if you write SIMD code, it requires 16 byte alignment.
That does not mean every member is aligned on an 8byte boundary. Read a little more carefully:
the smaller member type or n-byte boundaries
The key here is the first part- "smaller member type". That means that members with less alignment might be aligned less, effectively.
struct x {
char c;
int y;
};
std::cout << sizeof(x);
std::cout << "offsetof(x, c) = " << offsetof(x, c) << '\n';
std::cout << "offsetof(x, c) = " << offsetof(x, y) << '\n';
This yields 8, 0, 4- meaning that in fact, the int is only padded to a 4byte alignment.
Related
I am trying to port embed code in windows platform.
I have come across below problem I am posting a sample code here.
here even after I use int24 size remains 12 bytes in windows why ?
struct INT24
{
INT32 data : 24;
};
struct myStruct
{
INT32 a;
INT32 b;
INT24 c;
};
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char myArr[11] = { 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF };
myStruct *p = (myStruct*)myArr;
cout << sizeof(*p);
}
There are two reasons, each of which would be enough by themselves.
Presumably the size of INT32 is 4 bytes. The size of INT24 is also 4 bytes, because it contains a INT32 bit field. Since, myStruct contains 3 members of size 4, its size must therefore be at least 12.
Presumably the alignment requirement of INT32 is 4. So, even if the size of INT24 were 3, the size of myStruct would still have to be 12, because it must have at least the alignment requirement of INT32 and therefore the size of myStruct must be padded to the nearest multiple of 4.
any way or workaround ?
This is implementation specific, but the following hack may work for some compilers/cpu combinations. See the manual of your compiler for the syntax for similar feature, and the manual for your target cpu whether it supports unaligned memory access. Also do realize that unaligned memory access does have a performance penalty.
#pragma pack(push, 1)
struct INT24
{
INT32 data : 24;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct myStruct
{
INT32 a;
INT32 b;
INT24 c;
};
#pragma pack(pop)
Packing a bit field might not work the same in all compilers. Be sure to check how yours behaves.
I think that a standard compliant way would be to store char arrays of sizes 3 and 4, and whenever you need to read or write one of the integer, you'd have to std::memcpy the value. That would be a bit burdensome to implement and possibly also slower than the #pragma pack hack.
Sadly for you, the compiler in optimising the code for a particular architecture reserves the right to pad out the structure by inserting spaces between members and even at the end of the structure.
Using a bit field does not reduce the size of the struct; you still get the whole of the "fielded" type in the struct.
The standard guarantees that the address of the first member of a struct is the same as the address of the struct, unless it's a polymorphic type.
But all is not lost: you can rely on the fact that an array of char will always be contiguous and contain no packing.
If CHAR_BIT is defined as 8 on your system (it probably is), you can model an array of 24 bit types on an array of char. If it's not 8 then even this approach will not work: I'd then suggest resorting to inline assembly.
I was testing a class alignment and found strange behavior. I tested it with VS2012 compiler setting 4 and 8 bytes alignment setting but in each case output is same.
class Alignemnt{
public:
Alignemnt():a(){}
int a;
};
class Alignemnt_1{
public:
int a;
char array[2];
};
class Alignemnt_2{
public:
int a;
char array[2];
int x;
};
std::cout << "Sizeof(Alignemnt) :" <<sizeof(Alignemnt) << std::endl;
std::cout << "Sizeof(Alignemnt_1) :" <<sizeof(Alignemnt_1) << std::endl;
std::cout << "Sizeof(Alignemnt_2) :" <<sizeof(Alignemnt_2) << std::endl;
Every time output is:
Sizeof(Alignemnt) : 4
Sizeof(Alignemnt_1) : 8
Sizeof(Alignemnt_2) : 12
I think, Alignemnt_2 size should be 16 byte.
I assume you are referring to the /Zp switch, which lets you control maximum struct member alignment:
When you specify this option, each structure member after the first is stored on either the size of the member type or n-byte boundaries (where n is 1, 2, 4, 8, or 16), whichever is smaller.
Since you are not using a struct member with an alignment of more than 4 bytes (sizeof(int) and alignof(int) is both 4), all settings of 4 bytes and above will lead to exactly the same behavior.
If you want to specify the exact alignment of a structure member, consider using the standard C++ alignas which allows you to specify the exact alignment a member is supposed to have (VS 2012 should support it iirc).
See the result of using alignas.
Alignment shouldn't change the size of your object, just the starting address of the objects. For instance, an 8 byte aligned object could be at address 0x100000 or 0x100008, or really any address ending in 0 or 8 when written in hex but not 0x100004.
No.
Aligment 2 is fine.
You have 2 chars next to each other, that means you have 2 out of 4 bytes used. The packing will align it to 4 bytes, and then you will end up with 4 + 4 +4 .
If you want to end up to 16 you can try the following declaration :
{
char a;
int b;
char c;
int d;
}
I'm working on a 32-bit machine, so I suppose that the memory alignment should be 4 bytes. Say I have this struct:
typedef struct {
unsigned short v1;
unsigned short v2;
unsigned short v3;
} myStruct;
The plain added size is 6 bytes, and I suppose that the aligned size should be 8, but sizeof(myStruct) returns me 6.
However if I write:
typedef struct {
unsigned short v1;
unsigned short v2;
unsigned short v3;
int i;
} myStruct;
the plain added size is 10 bytes, aligned size shall be 12, and this time sizeof(myStruct) == 12.
Can somebody explain what is the difference?
At least on most machines, a type is only ever aligned to a boundary as large as the type itself [Edit: you can't really demand any "more" alignment than that, because you have to be able to create arrays, and you can't insert padding into an array]. On your implementation, short is apparently 2 bytes, and int 4 bytes.
That means your first struct is aligned to a 2-byte boundary. Since all the members are 2 bytes apiece, no padding is inserted between them.
The second contains a 4-byte item, which gets aligned to a 4-byte boundary. Since it's preceded by 6 bytes, 2 bytes of padding is inserted between v3 and i, giving 6 bytes of data in the shorts, two bytes of padding, and 4 more bytes of data in the int for a total of 12.
Forget about having different members, even if you write two structs whose members are exactly same, with a difference is that the order in which they're declared is different, then size of each struct can be (and often is) different.
For example, see this,
#include <iostream>
using namespace std;
struct A
{
char c;
char d;
int i;
};
struct B
{
char c;
int i; //note the order is different!
char d;
};
int main() {
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
}
Compile it with gcc-4.3.4, and you get this output:
8
12
That is, sizes are different even though both structs has same members!
Code at Ideone : http://ideone.com/HGGVl
The bottomline is that the Standard doesn't talk about how padding should be done, and so the compilers are free to make any decision and you cannot assume all compilers make the same decision.
By default, values are aligned according to their size. So a 2-byte value like a short is aligned on a 2-byte boundary, and a 4-byte value like an int is aligned on a 4-byte boundary
In your example, 2 bytes of padding are added before i to ensure that i falls on a 4-byte boundary.
(The entire structure is aligned on a boundary at least as big as the biggest value in the structure, so your structure will be aligned to a 4-byte boundary.)
The actual rules vary according to the platform - the Wikipedia page on Data structure alignment has more details.
Compilers typically let you control the packing via (for example) #pragma pack directives.
Assuming:
sizeof(unsigned short) == 2
sizeof(int) == 4
Then I personally would use the following (your compiler may differ):
unsigned shorts are aligned to 2 byte boundaries
int will be aligned to 4 byte boundaries.
typedef struct
{
unsigned short v1; // 0 bytes offset
unsigned short v2; // 2 bytes offset
unsigned short v3; // 4 bytes offset
} myStruct; // End 6 bytes.
// No part is required to align tighter than 2 bytes.
// So whole structure can be 2 byte aligned.
typedef struct
{
unsigned short v1; // 0 bytes offset
unsigned short v2; // 2 bytes offset
unsigned short v3; // 4 bytes offset
/// Padding // 6-7 padding (so i is 4 byte aligned)
int i; // 8 bytes offset
} myStruct; // End 12 bytes
// Whole structure needs to be 4 byte aligned.
// So that i is correctly aligned.
Firstly, while the specifics of padding are left up to the compiler, the OS also imposes some rules as to alignment requirements. This answer assumes that you are using gcc, though the OS may vary
To determine the space occupied by a given struct and its elements, you can follow these rules:
First, assume that the struct always starts at an address that is properly aligned for all data types.
Then for every entry in the struct:
The minimum space needed is the raw size of the element given by sizeof(element).
The alignment requirement of the element is the alignment requirement of the element's base type.
Notably, this means that the alignment requirement for a char[20] array is the same as
the requirement for a plain char.
Finally, the alignment requirement of the struct as a whole is the maximum of the alignment requirements of each of its elements.
gcc will insert padding after a given element to ensure that the next one (or the struct if we are talking about the last element) is correctly aligned. It will never rearrange the order of the elements in the struct, even if that will save memory.
Now the alignment requirements themselves are also a bit odd.
32-bit Linux requires that 2-byte data types have 2-byte alignment (their addresses must be even). All larger data types must have 4-byte alignment (addresses ending in 0x0, 0x4, 0x8 or 0xC). Note that this applies to types larger than 4 bytes as well (such as double and long double).
32-bit Windows is more strict in that if a type is K bytes in size, it must be K byte aligned. This means that a double can only placed at an address ending in 0x0 or 0x8. The only exception to this is the long double which is still 4-byte aligned even though it is actually 12-bytes long.
For both Linux and Windows, on 64-bit machines, a K byte type must be K byte aligned. Again, the long double is an exception and must be 16-byte aligned.
Each data type needs to be aligned on a memory boundary of its own size. So a short needs to be on aligned on a 2-byte boundary, and an int needs to be on a 4-byte boundary. Similarly, a long long would need to be on an 8-byte boundary.
The reason for the second sizeof(myStruct) being 12 is the padding that gets inserted between v3 and i to align i at a 32-bit boundary. There is two bytes of it.
Wikipedia explains the padding and alignment reasonably clearly.
In your first struct, since every item is of size short, the whole struct can be aligned on short boundaries, so it doesn't need to add any padding at the end.
In the second struct, the int (presumably 32 bits) needs to be word aligned so it inserts padding between v3 and i to align i.
Sounds like its being aligned to bounderies based on the size of each var, so that the address is a multiple of the size being accessed(so shorts are aligned to 2, ints aligned to 4 etc), if you moved one of the shorts after the int, sizeof(mystruct) should be 10. Of course this all depends on the compiler being used and what settings its using in turn.
The standard doesn't say much about the layout of structs with complete types - it's up to to the compiler. It decided that it needs the int to start on a boundary to access it, but since it has to do sub-boundary memory addressing for the shorts there is no need to pad them
why the size of the class cl1 in the following code is 8 but not 5, while the size of class cl2 is 1?
class cl1 {
public:
int n;
char cb;
cl1();
~cl1();
};
class cl2 {
public:
char cb;
cl2();
~cl2();
};
The compiler is free to insert padding in between and after class members in order to ensure that variables are properly aligned, etc. Exactly what padding is inserted is up to the implementation. In this case, I'd guess that the compiler is adding 3 bytes of padding after cl1::cb, perhaps to ensure that the next variable in memory is aligned on a 4-byte boundary.
The largest member of cl1 (n) is 4 bytes, so the size of cl1 is padded up to the nearest 4 bytes (8 in this case) so that an array of cl1 objects does not create n members which are not aligned to 4-byte addresses. Most processors really hate misaligned multi-byte values, either suffering performance losses (two memory cycles to access one value) or outright crashes (alignment exceptions).
There is no guarantee that this will be consistent from compiler to compiler or platform to platform.
This is all due to padding. More info can be found, for example, here
The thing is that the addresses of both the object and its members should be properly aligned for OS and Hardware - specific reasons. Thus the result. The problem of padding is complicated by the fact that objects in an array must be located consecutively, without any space in between, and ALL should be properly aligned.
It is because of structure padding by the compiler. If you want to remove the padding, try #pragma pack(1) and you should get 5 and 1 as expected.
While you're exploring the size of struct and how padding is done, let me tell you an interesting thing. The size of struct not only depends on the members, but also on the order of their declaration. For example, size of the following structs is different, even though both has same number of members of same types, the only difference is the order of their declaration!
struct A
{
int a;
char b;
char c;
};
struct B
{
char b;
int a;
char c;
};
cout << "sizeof(A) = " << sizeof(A) << endl;
cout << "sizeof(B) = " << sizeof(B) << endl;
Output:
sizeof(A) = 8
sizeof(B) = 12
Online Demo at Ideone: http://www.ideone.com/8OoxX
Are the members of a structure packed in C/C++?
By packed I mean that they are compact and among the fields there aren't memory spaces.
That isn't what aligned means, and no, no particular alignment or packing is guaranteed. The elements will be in order, but the compiler can insert padding where it chooses. This actually creates (useful) alignment. E.g., for a x86:
struct s
{
char c;
int i;
};
there will probably (but not necessarily) be three bytes between c and i. This allows i to be aligned on a word boundary, which can provide much faster memory access (on some architectures, it's required).
From C99 ยง6.7.2.1:
Each non-bit-field member of a
structure or union object is aligned
in an implementation- defined manner
appropriate to its type.
What you are asking for is packing, and alignment is different. Both are outside of the scope of the language and are specific for each implementation. Take a look here.
Generally not. Some info here.
Depending on the compiler, you can introduce pragmas to help (from the link above):
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
struct MyPackedData
{
char Data1;
long Data2;
char Data3;
};
#pragma pack(pop) /* restore original alignment from stack */
Typically (but under no guarantees), members of a struct are word-aligned. This means that a field less than the size of a word will be padded to take up an entire word.
However, when the next member of the struct can also fit inside the same word, then the compiler will put both members into the same word. This is more efficient space-wise, but depending on your platform, retrieving said members might be more expensive computationally.
On my 32-bit system using GCC under Cygwin, this program...
#include <iostream>
struct foo
{
char a;
int b;
char c;
};
int main(int argc, char** argv)
{
std::cout << sizeof(foo) << std::endl;
}
outputs '12' because both chars are word-aligned and take up 4 bytes each.
However, switch the struct to
struct foo
{
char a;
char c;
int b;
};
and the output is '8' because both chars next to each other can fit in a single word.
It is possible to pack bytes in order to conserve memory. For instance, pack(2) will tell members that longer than a byte to pack to two-bytes in order to maintain a two-byte boundary so that any padding members are two bytes long. Sometimes packing is used as part of a standard communication protocol where it expects a certain size. Here is what Wikipedia has to say about C/C++ and padding:
Padding is only inserted when a
structure member is followed by a
member with a larger alignment
requirement or at the end of the
structure. By changing the ordering of
members in a structure, it is possible
to change the amount of padding
required to maintain alignment. For
example, if members are sorted by
ascending or descending alignment
requirements a minimal amount of
padding is required. The minimal
amount of padding required is always
less than the largest alignment in the
structure. Computing the maximum
amount of padding required is more
complicated, but is always less than
the sum of the alignment requirements
for all members minus twice the sum of
the alignment requirements for the
least aligned half of the structure
members.
Although C and C++ do not allow the
compiler to reorder structure members
to save space, other languages might.
Since in struct's, the compiler treats things as words, sometimes care must be taken if you are relying on the size of the struct to be a certain size. For instance, aligning char vs int.
They are not packed by default. Instead, they are word-aligned depending on how your machine is set up. If you do want them to be packed. Then you can use __attribute__((__packed__)) at the end of your struct declaration like this:
struct abc {
char a;
int b;
char c;
}__attribute__((__packed__));
Then, for
struct abc _abc;
_abc will be packed.
Reference: Specific structure packing when using the GNU C Compiler
Seeing some outputs of the same structure's variations may give a clue about what is going on. After reading this, if I did not get it wrong, small types will be padded to be a word-lengths.
struct Foo {
char x ; // 1 byte
int y ; // 4 byte
char z ; // 1 byte
int w ; // 4 byte
};
struct FooOrdered {
char x ; // 1 byte
char z ; // 1 byte
int y ; // 4 byte
int w ; // 4 byte
};
struct Bar {
char x ; // 1 byte
int w ; // 4 byte
};
struct BarSingleType {
char x ; // 1 byte
};
int main(int argc, char const *argv[]) {
cout << sizeof(Foo) << endl;
cout << sizeof(FooOrdered) << endl;
cout << sizeof(Bar) << endl;
cout << sizeof(BarSingleType) << endl;
return 0;
}
In my environment output was like this:
16
12
8
1