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 6 years ago.
I was trying to find out the sizeof a structure, which I thought should show up as 24 bytes on my 64 bit Mac OS, instead it was shown as 32 bytes. what am i missing?
#include<stdio.h>
int main() {
struct Test{
int a;
int *b;
char *c;
float d;
}m;
int size = sizeof(m);
printf("%d\n",size);
}
Any of the field is aligned to its minimal alignment which is 4 for ints and floats and 8 for pointers. There will be padding and memory unused before such alignment. The full structure is aligned to 16 due to SSE requirements:
a: offset 0
b: offset 8 (4 bytes padding before)
c: offset 16
d: offset 24
padding 4 bytes to align to 16 bytes.
Alignment. 4 bytes int, padding 4 bytes, 8 bytes pointer, eight bytes pointer, 4 bytes float, 4 bytes padding.
Related
I have a stuct a of size 16 bytes and another struct b which contains a.
Why is struct b of size 40 bytes? Where is the additional padding exactly?
typedef struct {
} a;
typedef struct {
a x;
} b;
The struct a has 4-byte alignment since that's the largest alignment of any of its members (i.e. float).
From there, the fields of b are laid out with the following offsets:
w: 0
padding: 1 - 3
x: 4 - 19
padding: 20 - 23
y: 24 - 31
z: 32 - 33
padding: 34 - 39
The member with the largest alignment is y which has 8-byte alignment. This results in 4 bytes of padding between x and y, as well as 6 bytes of padding at the end.
The padding can be minimized by moving z to between w and x. Then you would have:
w: 0
padding: 1
z: 2 - 4
x: 4 - 19
padding: 20 - 23
y: 24 - 31
For a total size of 32.
Alignment is of course entirely up to the implementation, but this is what you'll most likely see. The Lost Art of C Structure Packing goes into this in much more detail.
The algorithm compilers typically use to lay out structures is described in this answer.
For your structure a and characteristics typical in current C implementations (described below):
The char w has an alignment requirement of 1 byte, so it needs no padding and is placed at offset 1. It occupies 1 byte.
The float x has an alignment requirement of 4 bytes, so 3 bytes are needed to bring the current offset from 1 byte to 4 bytes. Then it occupies 4 bytes, giving us 8 total so far.
The short int y has an alignment requirement of 2 bytes, so it needs no padding from the current offset of 8 bytes. It occupies 2 bytes, bringing the total to 10.
The float z has an alignment requirement of 4 bytes, so it needs 2 bytes to bring the offset from 10 bytes to 12 bytes. It occupies 4 bytes, bringing the total to 16.
The alignment requirement of the structure is 4 bytes (the strictest alignment requirement of its members), and the current total is 16 bytes, which is already a multiple of 4, so no padding at the end is needed.
Thus the size of a is 16 bytes.
For your structure b:
The char w has an alignment requirement of 1 byte, so it needs no padding and is placed at offset 1. It occupies 1 byte.
The a x has an alignment requirement of 4 bytes, so 3 bytes of padding are needed to bring the offset from 1 byte to 4 bytes. It occupies 16 bytes, bringing the total to 20.
The double y has an alignment requirement of 8 bytes, so 4 bytes of padding are needed to bring the offset from 20 bytes to 24. It occupies 8 bytes, bringing the total to 32.
The short int z has an alignment requirement of 2 bytes, so no padding is needed from the current offset of 32 bytes. It occupies 2 bytes, bringing the total to 34.
The alignment requirement of the structure is 8 bytes (the strictest alignment requirement of its members), so 6 bytes of padding is needed to bring the total size from 34 bytes to 40.
Thus the size of b is 40 bytes.
The characteristics used are:
char has size 1 byte and alignment requirement 1 byte. This is a fixed property of the C standard.
short int has size 2 bytes and alignment requirement 2 bytes.
float has size 4 bytes and alignment requirement 4 bytes.
double has size 8 bytes and alignment requirement 8 bytes. (Having an alignment requirement of 4 bytes instead of 8 would not be very weird; hardware might load and store doubles in 32-bit chunks and not care whether either of them were 8-byte aligned.)
The C implementation does not use more padding or stricter alignment than required by the sizes and alignment requirements of structure members. (This is not mandated by the C standard, but there is generally no reason to do otherwise.)
You seem to understand why the size of a is 16 bytes, and I'll also assume that you see why a has an alignment requirement of 4 bytes (see the note about arrays in the discussion below on the alignment of b). From that, we can see that, in b, we will have 3 bytes of padding between w and x.
Now, on your platform (as on many/most), a double has a size and alignment requirement of 8 bytes – so, after the 20 bytes up to the end of x (1 for w, 3 for padding and 16 for x), we need to add 4 bytes padding between x and y, to align that double. Thus, we have now added 12 bytes to our total, giving a running size (up to y) of 32 bytes.
The z member takes another 2 bytes (running size of 34) but, as the alignment requirement of the overall b structure must be 8 bytes (so that, in an array of such, every element's y will remain properly aligned), we need a further 6 bytes to reach a size (40) that is a multiple of 8.
Here is a breakdown of the memory layout:
typedef struct {
char w; // 1 byte: total = 1
// 3 bytes padding: total = 4
float x; // 4 bytes: total = 8
short int y;// 2 bytes: total = 10
// 2 bytes padding: total = 12
float z; // 4 bytes: TOTAL = 16
} a;
typedef struct {
char w; // 1 byte: total = 1
// 3 bytes padding: total = 4
a x; // 16 bytes: total = 20
// 4 bytes padding: total = 24
double y; // 8 bytes: total = 32
short int z;// 2 bytes: total = 34
// 6 bytes padding: TOTAL = 40
} b;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I know what padding is and how alignment works. Given the struct below:
typedef struct {
char word[10];
short a;
int b;
} Test;
I don't understand how C interprets and aligns the char array inside the struct. It should be 9 chars + terminator and it should be regarded as the longest like this:
| - _ - _ - _ - _ - word - _ - _ - _ - _ - |
| - a - | - _ - b - _ - | padding the remaining 4 bytes
The "-" represents a byte and "_" separates the bytes. So we have the 10 bytes long word, the 2 bytes long a and the 4 bytes long b and padding of 4 bytes. But when I print sizeof(Test) it returns 16.
EDIT: I got it.
In a struct like
struct {
char word[10];
short a;
int b;
}
you have the following requirements:
a needs an even offset. As the char arry before it has an even length, there is no need for padding. So a sits at offset 10.
b needs an offset which is dividible by 4. 12 is dividible by 4, so 12 is a fine offset for b.
The whole struct needs a size which is dividible by 4, because every b in an array of this struct needs to have the said requirement. But as we are currently at size 16, we don't need any padding.
WWWWWWWWWWAABBBB
|-- 10 --| 2 4 = 16
Compare this with
struct {
char word[11];
short a;
int b;
}
Here, a would have offset 11. This is not allowed, thus padding is inserted. a is fine with an offset of 12.
b would then get an offset of 14, which isn't allowed either, so 2 bytes are added. b gets an offset of 16. The whole struct gets a size of 20, which is fine for all subsequent items in an array.
WWWWWWWWWWW.AA..BBBB
|-- 11 --|1 2 2 4 = 20
Third example:
struct {
char word[11];
int b;
short a;
}
(note the changed order!)
b is happy with an offset of 12 (it gets 1 padding byte),
a is happy with an offset of 16. (no padding before it.)
After the struct, however, 2 bytes of padding are added so that the struct aligns with 4.
WWWWWWWWWW..BBBBAA..
|-- 10 --| 2 4 2 2 = 20
In:
struct
{
char word[10];
short a;
int b;
}
and given two-byte short and four-byte int, the structure is laid out in memory:
Offset Member
0 word[0]
1 word[1]
2 word[2]
3 word[3]
4 word[4]
5 word[5]
6 word[6]
7 word[7]
8 word[8]
9 word[9]
10 a
11 a
12 b
13 b
14 b
15 b
To get the layout described in the question, where a and b overlap word, you need to use a struct inside a union:
typedef union
{
char word[10];
struct { short a; int b; };
} Test;
Generally, each variable will be aligned on a boundary of its size.
(unless attributes such as packed are applied)
A complete discussion is on Wikipedia, which says in part:
A char (one byte) will be 1-byte aligned.
A short (two bytes) will be 2-byte aligned.
An int (four bytes) will be 4-byte aligned.
A long (four bytes) will be 4-byte aligned.
A float (four bytes) will be 4-byte aligned.
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on
Linux (8-byte with -malign-double compile time option).
A long long (eight bytes) will be 4-byte aligned.
So your structure is laid out as:
typedef struct {
char word[10];
// Aligned with beginning of structure; takes bytes 0-9
short a;
// (assuming short is 2-bytes)
// Previous member ends on byte 9, this one starts on byte-10.
// Byte 10 is a multiple of 2, so no padding necessary
// Takes bytes 10 and 11
int b;
// Previous member ends on byte 11, next byte is 12, which is a multiple of 4.
// No padding necessary
// Takes bytes 12, 13, 14, 15.
} Test;
Total size: 16 bytes.
If you want to play with it, change your word-array to 9 or 11 bytes,
or reverse the order of your short and int, and you'll see the size of the structure change.
This question already has answers here:
Structure Padding
(6 answers)
Closed 7 years ago.
struct test {
char c;
} x;
From my knowledge of structure padding, I expected the size of this structure to be 4 Bytes on a 32-bit system. Why does it show 1 byte?
You just have a char, in that case you won't need any alignment/padding.
If you try this you should see some alignment:
char *p; /* 4 or 8 bytes */
char c; /* 1 byte */
//char pad[3]; /* 3 bytes */
int x; /* 4 bytes */
There are different rules for different architectures, in this case the int has a 4byte alignment, which forces a padding of three bytes to be added.
source:
http://www.catb.org/esr/structure-packing/
In C, the strucute are padded to the current data size.
If you have a char will be aligned to 1B, for short to 2B and so on.
A quick rule is: size of previous elements + size of current element aligned to size of current element .
Here are some exaples:
struct
{
int a1; // 0 + 4 aligned to 4 => 4
char a2; // 4 + 1 aligned to 1 => 5
} // total size 5
struct
{
char a1; // 0 + 1 aligned to 1 => 1
int a2; // 1 + 4 aligned to 4 => 8
}
struct
{
char a1; // 0 + 1 aligned to 1 => 1
short a2; // 1 + 2 aligned to 2 => 4
int a3; // 4 + 4 aligned to 4 => 8
}
This rule is an effect of memory addressing:
Fastest way to read/write X byte memory is if that memory address is multiple of X. (This is how Intel processors optimise memory access by ignoring some bits of addressing).
Another padding is between structures in memory. If you have a structure with an int and a char(total size 5), in memory you will still have 3 bytes padding between them for memory access optimisation.
First up, I tried to go through the existing threads in stackoverflow regarding my question. Atleast, I was not able to find a thread which talks about my issue.
I am executing the following code for a 32 bit machine through
gcc -m32 -o size32 size.c
To the contrary, I find that the compiler is not adding the extra padding. I have not added the attribute flag. So I expect the compiler to pad extra bytes. Here is my issue.
struct s{
char c;
int i;
double d;
void *p;
};
struct s temp;
void *q;
double d1=10;
printf("size of struct = %d sizeof q = %d sizeof double = %d\n",sizeof(temp),sizeof(q),sizeof(d1));
The output was
size of struct = 20 sizeof q = 4 sizeof double = 8
This is my calculation. char(1 byte) + 3 bytes padding + int(4 bytes) + double(8 bytes) + (void*)(4 bytes) which is equal to 20 bytes plus 4 bytes due to the longest member alignment rule ( here double is 8 bytes, so struct should be aligned on a 8 byte boundary ) which finally sums to 24 bytes. So total size should be 24 bytes. Why is it showing only 20 bytes?
Thanks
Chid
On Linux, unless you pass -malign-double to the compiler, doubles are only aligned at 4 byte boundaries, so the struct will not require extra padding.
See documentation here.
typedef struct structc_tag
{
char c;
double d;
int s;
} structc_t;
I read in a blog that this will take 24 bytes of data:
sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) + 4 byte padding = 1 + 7 + 8 + 4 + 4 = 24 bytes.
My question is why the 7 byte padding, why can't we use 3bytes of padding there and utilise next 8 bytes for double? And what is the need for last 4 bytes?
You need to consider what the happens if you allocate an array of these structures with malloc():
structc_t *p = malloc(2 * sizeof *p);
Consider a platform where sizeof(double) == 8, sizeof(int) == 4 and the required alignment of double is 8. malloc() always returns an address correctly aligned for storing any C type - so in this case a will be 8 byte aligned. The padding requirements then naturally fall out:
In order for a[0].d to be 8-byte aligned, there must therefore be 7 bytes of padding after a[0].c;
In order for a[1].d to be 8-byte aligned, the overall struct size must be a multiple of 8, so there must therefore be 4 bytes of padding after a[0].s.
If you re-order the struct from largest to smallest:
typedef struct structc_tag
{
double d;
int s;
char c;
} structc_t;
...then the only padding required is 3 bytes after .c, to make the structure size a multiple of 8. This results in the total size of the struct being 16, rather than 24.
It's platform dependent, but it depends on what double is aligned to. If it's aligned to 8 bytes, which appears to be this case, 3 bytes of padding won't cut it.
If double was aligned to 4 bytes, you'd be right and 3 bytes of padding would be used.