This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Memory Alignment in C/C++
(1 answer)
Closed 2 years ago.
class Test2
{
char pq;
long double qr;
};
class Test
{
double c;
int a;
char b;
Test2 z;
};
sizeof(Test2)=32
sizeof(Test)=48
Why sizeof(Test) is 48 on a 64-bit operating system?
It is all about memory alignment.
alignment uses to ensure types don't slip from one memory page to another. the compiler ensures the start address of a type is divided by its alignment.
For example: if a type has an alignment of 2 it can't start on an even address if it has an alignment of 4, the start address the last number must be 0,4,8 or c (hexadecimal). and so on, for alignment of 16, the start address (hex again) is always with 0 at the end.
Each type may have a different alignment.
You can use the alignof operator to tell each type's alignment.
You can use the old offsetof to tell what is the starting address of each member in your class.
It's correct ,
The size of class Test2 is 32 because of the max size variable you have is long double
char 1 byte
long double is 16 byte
so memory allocation is like
-----------------------------------------------------------
char 1 byte |.....padding 15 bytes | long double 16 bytes |
-----------------------------------------------------------
total 32
for class Test the largest size variable is of 8 bytes
so memory allocation is
-------------------------------------------------------------------------------------
double 8 byte |4 byte int then 1 byte char | padding 3 bytes | 32 byte Test2 object
-------------------------------------------------------------------------------------
total 48
Related
Someone explain me how does the order of the member declaration inside a class determines the size of that class.
For Example :
class temp
{
public:
int i;
short s;
char c;
};
The size of above class is 8 bytes.
But when the order of the member declaration is changed as below
class temp
{
public:
char c;
int i;
short s;
};
then the size of class is 12 bytes.
How?
The reason behind above behavior is data structure alignment and padding. Basically if you are creating a 4 byte variable e.g. int, it will be aligned to a four byte boundary i.e. it will start from an address in memory, which is multiple of 4. Same applies to other data types. 2 byte short should start from even memory address and so on.
Hence if you have a 1 byte character declared before the int (assume 4 byte here), there will be 3 free bytes left in between. The common term used for them is 'padded'.
Data structure alignment
Another good pictorial explanation
Reason for alignment
Padding allows faster memory access i.e. for cpu, accessing memory areas that are aligned is faster e.g. reading a 4 byte aligned integer might take a single read call where as if an integer is located at a non aligned address range (say address 0x0002 - 0x0006), then it would take two memory reads to get this integer.
One way to force compiler to avoid alignment is (specific to gcc/g++) to use keyword 'packed' with the structure attribute. packed keyword Also the link specifies how to enforce alignment by a specific boundary of your choice (2, 4, 8 etc.) using the aligned keyword.
Best practice
It is always a good idea to structure your class/struct in a way that variables are already aligned with minimum padding. This reduces the size of the class overall plus it reduces the amount of work done by the compiler i.e. no rearrangement of structure. Also one should always access member variables by their names in the code, rather than trying to read a specific byte from structure assuming a value would be located at that byte.
Another useful SO question on performance advantage of alignment
For the sake of completion, following would still have a size of 8 bytes in your scenario (32 bit machine), but it won't get any better since full 8 bytes are now occupied, and there is no padding.
class temp
{
public:
int i;
short s;
char c;
char c2;
};
class temp
{
public:
int i; //size 4 alignment 4
short s; //size 2 alignment 2
char c; //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4
temp[i[0-4];s[4-2];c[6-7]]] -> 8
Padding in (7-8)
class temp
{
public:
char c; //size 1 alignment 1
int i; //size 4 alignment 4
short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4
temp[c[0-1];i[4-8];s[8-10]]] -> 12
Padding in (1-4) and (10-12)
I'm trying to understand struct and class padding in depth, so I devised an example I considered more challenging than many of the examples I found in tutorials on the topic. I compiled it in an x64 machine with g++, without enabling any code optimization. My code is as follows:
class Example
{
private:
long double foobar; // 10 bytes + 6 padded bytes as double follows
double barfoo; // 8 bytes + 8 padded bytes
static float barbar; // didn't count as it's a static member
float *fooputs; // 8 bytes + 8 padded bytes
int footsa; // 4 bytes, stored in the padded portion of float
char foo; // 1 byte, stored in the padded portion of float
public:
int function1(int foo) { return 1; }
void function2(int bar) { foobar = bar; }
};
int main()
{
std::cout << sizeof(Example) << std::endl; // 48 bytes
return 0;
}
Although I see that the size of Example is 48 bytes, I expected it to be 37 bytes. The argumentation on my expectation is as follows:
foobar needs 10 bytes. As double follows, 6 more bytes are needed for padding.
barfoo needs 8 bytes, as it's a double. No need for padding, as mod(16,8) == 0
*fooputs needs 8 bytes, as it's a pointer in an x64 architecture. No need for padding, as mod(24,8) == 0
footsa needs 4 bytes as an int. No need for padding, as mod(32,4) == 0
foo needs 1 byte as a char. No need for padding.
As the result is different that the expected, I tried to understand how C++ evaluated the size of Example to 48 bytes by commenting in and out class members. So, besides of the argumentation for foobar I assumed the justifications I'm writing in my inline comments for each member.
Could anyone explain me how the size is evaluated to 48 bytes and if my justifications are correct?
You forget about the final padding. sizeof returns a number of bytes between two adjacent members in an array. In your case, alignof(long double) is very likely 16, therefore each Example instance requires to be at 16-byte aligned address.
Consequently, if you have first instance of Example at a 16-bytes aligned address A, and then there are 37 bytes required by members, the next Example instance cannot be stored at A + 37 bytes, but it needs to be stored at A + k * 16. The smallest possible k that satisfies k * 16 >= 37 is 3. Which finally gives you the number of bytes between two Example instances in an array 3 * 16 = 48, which is exactly sizeof(Example).
This question already has answers here:
Why is my union's size bigger than I expected?
(5 answers)
Closed 2 years ago.
I have the following union :
union Variant{
char txt[10];
double floating_point;
};
The confusion comes when I try to print sizeof(Variant) , which outputs 16 bytes.
Why doesn't it output 10 bytes instead of 16 ? if union takes up as much memory as its largest member, it should do max(sizeof(char[10]), sizeof(double)) no ?
Where does the 6 bytes comes from anyway, if in my system a double takes 8 bytes ?
Because of the alignment on the 8 bytes boundary, since the size of the union's largest member double is probably 8 bytes on your machine. If you had an int instead of double, the size would probably be 12.
The size of your char array is 10 bytes, because it has ten elements. Which is greater than your largest member double size, which is 8. So, the next possible alignment is 2 * 8 which is 16.
If your array had 8 elements or less, the size of the union would be 8, etc.
Why doesn't it output 10 bytes instead of 16 ? if union takes up as much mamory as its largest member, it should do max(sizeof(char[10]), sizeof(double)) no ?
The size of a structure or a class is a multiple of the alignment of a member with the largest alignment requirement. Here, that member is double, whose alignment is 8, i.e. alignof(double) == 8 and alignof(Variant) == alignof(double).
Someone explain me how does the order of the member declaration inside a class determines the size of that class.
For Example :
class temp
{
public:
int i;
short s;
char c;
};
The size of above class is 8 bytes.
But when the order of the member declaration is changed as below
class temp
{
public:
char c;
int i;
short s;
};
then the size of class is 12 bytes.
How?
The reason behind above behavior is data structure alignment and padding. Basically if you are creating a 4 byte variable e.g. int, it will be aligned to a four byte boundary i.e. it will start from an address in memory, which is multiple of 4. Same applies to other data types. 2 byte short should start from even memory address and so on.
Hence if you have a 1 byte character declared before the int (assume 4 byte here), there will be 3 free bytes left in between. The common term used for them is 'padded'.
Data structure alignment
Another good pictorial explanation
Reason for alignment
Padding allows faster memory access i.e. for cpu, accessing memory areas that are aligned is faster e.g. reading a 4 byte aligned integer might take a single read call where as if an integer is located at a non aligned address range (say address 0x0002 - 0x0006), then it would take two memory reads to get this integer.
One way to force compiler to avoid alignment is (specific to gcc/g++) to use keyword 'packed' with the structure attribute. packed keyword Also the link specifies how to enforce alignment by a specific boundary of your choice (2, 4, 8 etc.) using the aligned keyword.
Best practice
It is always a good idea to structure your class/struct in a way that variables are already aligned with minimum padding. This reduces the size of the class overall plus it reduces the amount of work done by the compiler i.e. no rearrangement of structure. Also one should always access member variables by their names in the code, rather than trying to read a specific byte from structure assuming a value would be located at that byte.
Another useful SO question on performance advantage of alignment
For the sake of completion, following would still have a size of 8 bytes in your scenario (32 bit machine), but it won't get any better since full 8 bytes are now occupied, and there is no padding.
class temp
{
public:
int i;
short s;
char c;
char c2;
};
class temp
{
public:
int i; //size 4 alignment 4
short s; //size 2 alignment 2
char c; //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4
temp[i[0-4];s[4-2];c[6-7]]] -> 8
Padding in (7-8)
class temp
{
public:
char c; //size 1 alignment 1
int i; //size 4 alignment 4
short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4
temp[c[0-1];i[4-8];s[8-10]]] -> 12
Padding in (1-4) and (10-12)
Someone explain me how does the order of the member declaration inside a class determines the size of that class.
For Example :
class temp
{
public:
int i;
short s;
char c;
};
The size of above class is 8 bytes.
But when the order of the member declaration is changed as below
class temp
{
public:
char c;
int i;
short s;
};
then the size of class is 12 bytes.
How?
The reason behind above behavior is data structure alignment and padding. Basically if you are creating a 4 byte variable e.g. int, it will be aligned to a four byte boundary i.e. it will start from an address in memory, which is multiple of 4. Same applies to other data types. 2 byte short should start from even memory address and so on.
Hence if you have a 1 byte character declared before the int (assume 4 byte here), there will be 3 free bytes left in between. The common term used for them is 'padded'.
Data structure alignment
Another good pictorial explanation
Reason for alignment
Padding allows faster memory access i.e. for cpu, accessing memory areas that are aligned is faster e.g. reading a 4 byte aligned integer might take a single read call where as if an integer is located at a non aligned address range (say address 0x0002 - 0x0006), then it would take two memory reads to get this integer.
One way to force compiler to avoid alignment is (specific to gcc/g++) to use keyword 'packed' with the structure attribute. packed keyword Also the link specifies how to enforce alignment by a specific boundary of your choice (2, 4, 8 etc.) using the aligned keyword.
Best practice
It is always a good idea to structure your class/struct in a way that variables are already aligned with minimum padding. This reduces the size of the class overall plus it reduces the amount of work done by the compiler i.e. no rearrangement of structure. Also one should always access member variables by their names in the code, rather than trying to read a specific byte from structure assuming a value would be located at that byte.
Another useful SO question on performance advantage of alignment
For the sake of completion, following would still have a size of 8 bytes in your scenario (32 bit machine), but it won't get any better since full 8 bytes are now occupied, and there is no padding.
class temp
{
public:
int i;
short s;
char c;
char c2;
};
class temp
{
public:
int i; //size 4 alignment 4
short s; //size 2 alignment 2
char c; //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4
temp[i[0-4];s[4-2];c[6-7]]] -> 8
Padding in (7-8)
class temp
{
public:
char c; //size 1 alignment 1
int i; //size 4 alignment 4
short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4
temp[c[0-1];i[4-8];s[8-10]]] -> 12
Padding in (1-4) and (10-12)