This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 7 years ago.
I already read this question: struct padding in c++ and this one Why isn't sizeof for a struct equal to the sum of sizeof of each member?
and I know this isn't standardized but still I believe it's a legit question.
Why is the size of this struct 16 on a x64 system?
struct foo { char* b; char a;};
The effective size would be 8 + 1 = 9, but I know there's padding involved. Anyway I thought a would only be padded to reach the size of an int, i.e. with other 3 bytes giving a total of 12 bytes.
Is there any reason why the specific compiler (gcc) thought it should have 16 bytes as a size?
Wild guess: is it possible that the biggest type (e.g. double or in this case x64 pointer) will dictate the padding to use?
Likely the compiler is aligning the struct on an 8-byte word boundary to improve access speed. A struct size of 9 is probably going to slow down the CPU quite a bit with unaligned accesses (plus the stack pointer should never be on an odd address). A size of 12 (3 padding bytes), would work, but some operations, like the FPU operations, prefer an alignment of 8 or 16 bytes.
It is because of memory alignment. By default memory is not aligned on one bye order and this happens. Memory is allocated on 4-byte chunks on 32bit systems.
You can change this behavior by setting __attribute__((packed, aligned(x))) when you define your structure. By this memory is allocated on x-byte chunks.
Related
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).
This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Structure padding and packing
(11 answers)
Closed 7 years ago.
We know that the correct order of declaring variables in structures changes the size of a structure also because of padding. I have seen the reference here.
Suppose a structure is:
struct s {
char b; //1 for char
char c; //1 for char + 2 for padding
int a; //4 for int
}my_struct;
So the size of the my_struct is 8, but without padding it could be 6 which is less than 8.
So my question is: Why padding is done in structures? What is the necessity of this concept?
Because without padding the structure is of lesser size. My question is not related to when padding take place, it is more concerned about the concept of padding.
Many computer architectures have optimized memory access in an alignment different than 1 byte (usually, 1 word = 4 bytes). Aligned accesses is generally faster than unaligned ones (and sometimes, it is impossible to access unaligned data). For this reason, compilers pack the struct members in an optimally aligned fashion. In your example, it looks like the alignment is of size 2 bytes, thus b is at offset 0, c is at offset 2 and a is at offset 4, totaling 8 bytes (assuming a is 4 bytes long). Or, according to the inline comments, in your example, it looks like the optimal alignment is equal to the data size. Thus, b and c are adjacent because the size is 1 and so is the alignment, but a is 4 bytes long, and hence needs a 4-byte alignment.
At the bottom line - this is all very architecture dependent.
This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Why does a struct consisting of a char, short, and char (in that order), when compiled in C++ with 4-byte packing enabled, come to a 6-byte struct?
(3 answers)
Closed 9 years ago.
So I am currently a student and am having a programming couse.
Today we had about the use of sizeof in different classes(if it had 1 int or 2 int´s and so on)
One part of the example I found weird was this:
class TwoIntAndACharClass
{
public:
int x_;
int y_;
char z_;
};
and the part to test it
TwoIntAndACharClass o3b;
cout << "Sizeof TwoIntAndACharClass = " << sizeof(o3b) << "\n";
So in the program i could see a class with 1 char took 1 byte. So when I saw this I thought I would see 9 bytes and not 12
So first I thought that it was weird but after some time I came to the conclusion that it might save some kind of blocks of 4 bytes.
To be 100% sure that this was true I then tried adding a new variable into the class(a double variable of 8 bytes) and the total size increased from 12 bytes to now 24 bytes. That ment that the char now had to be 8 bytes long so my last theory failed.
My last theory was that it would take the biggest already declared variable and use the size of that for the char variable _z , as this worked with both long long int(8 bytes) and a double(also 8 bytes)
So my question is, is my last theory true - or is it something different making the char take more memory then needed? (my teacher did say that each compiler could handle this differently but I have tried it on microsoft visual studio and a friend tried it on another compiler with the same results, but is that really true, is it the way the compiler handle this?)
Sorry for my poor english.
sizeof gives you the size of the struct, not the sum of the sizes of its members. Due to alignment requirements (ints generally like to be aligned on natural boundaries; 4 bytes on most platforms), the compiler will pad the struct to 12 bytes, so that when you have multiple instances of the struct adjacent to each other (e.g. in an array), they stay correctly aligned.
Most compilers have some custom extension to control padding, e.g. #pragma pack in Microsoft's compiler.
I'm confused about unions and how they allocate memory. Say I have:
union Values
{
int ivalue;
double dvalue;
};
Values v;
So I know the int uses 4 bytes and the double uses 8 bytes, so there are 8 bytes allocated in total (I think), with that said how much memory would v use?
You've pretty much answered your own question: given a four-byte int and an 8-byte double, v would use 8 bytes of memory.
If unsure, you could compile and run a simple program that'll print out sizeof(v).
Given that int is 4 bytes and double is 8 bytes (which is not guaranteed by the language), sizeof (Values) is at least 8 bytes.
Most commonly it will be exactly 8 bytes (more generally, sizeof (int) or sizeof (double), whichever is larger), but compilers are permitted to add unnamed padding to structs and unions. For structs, any such padding can be between any two mebers, or after the last one; for unions, it can only be at the end.
The purpose of such padding is to allow for better alignment. For example, given:
union u {
char c[5];
int i;
};
if int is 4 bytes and requires 4-byte alignment, the compiler will have to add padding to make sizeof (union u) at least 8 bytes.
In your particular case, there's probably no reason to add any padding, but you shouldn't assume that there isn't any. If you need to know the size of the union, just use sizeof.
I have the following struct declaration and typedef in my code:
struct blockHeaderStruct {
bool allocated;
unsigned int length;
};
typedef struct blockHeaderStruct blockHeader;
When I do sizeof(blockheader), I get the value of 4 bytes back, but when I do sizeof(struct blockHeaderStruct), I get 8 bytes.
Why is this happening? Why am I not getting 5 back instead?
Firstly, you cannot do sizeof(blockHeaderStruct). That simply will not compile. What you can do is sizeof(struct blockHeaderStruct), which could indeed give you 8 bytes as result.
Secondly, getting a different result from sizeof(blockheader) is highly unlikely. Judging by your reference to sizeof(blockHeaderStruct) (which, again, will not even compile) your description of the problem is inaccurate. Take a closer look at what is it you are really doing. Most likely, you are taking a sizeof of a pointer type (which gives you 4), not a struct type.
In any case, try posting real code.
Looking at the definition of your struct, you have 1 byte value followed by 4 byte Integer. This integer needs to be allocated on 4 byte boundary, which will force compiler to insert a 3 byte padding after your 1 byte bool. Which makes the size of struct to 8 byte. To avoid this you can change order of elements in the struct.
Also for two sizeof calls returning different values, are you sure you do not have a typo here and you are not taking size of pointer or different type or some integer variable.
The most likely scenario is that you are actually looking at the size of a pointer, not the struct, on a 32-bit system.
However, int may be 2 bytes (16 bits). In that case, the expected size of the structure is 4:
2 bytes for the int
1 byte for the bool
round up to the next multiple of 2, because the size of the struct is usually rounded to a multiple of the size of its largest primitive member.
Nothing could explain sizeof(blockHeaderStruct) != sizeof(struct blockHeader), though, given that typedef. That is completely impossible.
Struct allocation normally occurs on a 4 byte boundary. That is the compiler will pad data types within a struct up to the 4 byte boundary before starting with the next data type. Given that this is c++ (bool is a sizeof 1) and not c (bool needs to be #define as something)
struct blockHeaderStruct {
bool allocated; // 1 byte followed by 3 pad bytes
unsigned int length; // 4 bytes
};
typedef struct blockHeaderStruct blockHeader;
typedef struct blockHeaderStruct *blockHeaderPtr;
A sizeof operation would result:
sizeof(blockHeader) == 8
sizeof(struct blockHeader) == 8
sizeof(blockHeaderPtr) == 4
(Note: The last entry will be 8 for a
64 bit compiler. )
There should be no difference in sizes between the first two lines of code. A typedef merely assigns an alias to an existing type. The third is taking the sizeof a pointer which is 4 bytes in a 32 bit machine and 8 bytes on a 64 bit machine.
To fix this, simply apply the #pragma pack directive before a structure is defined. This forces the compiler to pack on the specified boundary. Usually set as 1,2,or 4 (although 4 is normally the default and doesn't need to be set).
#include <stddef.h>
#include <stdio.h>
#pragma pack(1)
struct blockHeaderStruct {
bool allocated;
unsigned int length;
};
typedef struct blockHeaderStruct blockHeader;
int main()
{
printf("sizeof(blockHeader) == %li\n", sizeof(blockHeader));
printf("sizeof(struct blockHeader) == %li\n", sizeof(struct blockHeaderStruct));
return 0;
}
Compiled with g++ (Ubuntu
4.4.1-4ubuntu9) 4.4.1
Results in:
sizeof(blockHeader) == 5
sizeof(structblockHeader) == 5
You don't normally need this directive. Just remember to pack your structs efficiently. Group smaller data types together. Do not alternate < 4 byte datatypes and 4 byte data types as your structs will be mostly unused space. This can cause unnecessary bandwidth for network related applications.
I actually copied that snippet direct
from my source file.
OK.
When I do sizeof(blockheader), I get
the value of 4 bytes back
It looks like blockheader is typedef'ed somewhere and its type occupies 4 bytes or its type requires 4 byte alignment.
If you try sizeof(blockHeader) you'll get your type.
when I do sizeof(blockHeaderStruct), I
get 8 bytes.
The reason why alignment matters is that if you need an array of blockHeaders then you can compute how much memory you need. Or if you have an array and need to compute how much memory to copy, you can compute it.
If you want to align all struct members to addresses that are multiples of 1 instead of 4 or instead of your compiler's defaults, your compiler might offer a #pragma to do it. Then you'll save memory but accesses might be slower in order to access unaligned data.
Some compilers will optimize to always allocate data by powers of 2 (4 stays 4, but 5 is rounded up to 8).