I am using a structure, but unable to understand how the padding occurs. I am using a 64-bit system. The size of char is 1 byte, float is 4 byte and long is 8 byte in my system.
struct record{
char name[50];
float cost;
long num;
}stu;
Size: 64.
This result in size of: 64
struct record{
char name[50];
long num;
float cost;
}stu;
Size: 72.
I am not sure how padding takes place in both the cases.
Padding is used to maintain alignment of types. Processors tend to be more efficient if 4-byte types are aligned on addresses divisible by 4, for example.
struct record {
char name[50]; // offset 0 size 50 (type is size 1)
/* padding 2 bytes here */
float cost; // offset 52 (size 4, offset divisible by 4)
long num; // offset 56 (size 8, offset divisible by 8)
} stu; // total 64 (divisible by 8, (min of current packing size or largest member)
struct record {
char name[50]; // offset 0, size 50
/* padding 6 bytes here */
long num; // offset size 56, size 8, offset divisible by 8
float cost; // offset 64, size 4, offset divisible by 4
/* padding 4 bytes here */
} stu; // total 72, divisible by 8 (min of current packing size or largest member)
The trailing packing is needed in the case of contiguous arrays of structures to maintain natural alignment of types for each element of the array.
Related
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 and packing
(11 answers)
Closed 7 years ago.
struct
{
int m,s,l;
union
{
char c[10];
};
float p;
} a;
int main()
{
printf("%d",sizeof(a));
return 0;
}
according to the calculations ans must be 4*3+10+4=26 but DEV C++ compiler showing the output 28.
The principles of allocating local variables on stack are roughly the same for all systems
1 -- Stack grows from high addresses to low addresses
2 -- The order of declaration of your variables in your program corresponds to growth of stack
3 -- Each type has alignment - the address of any variable must be divisible by its size (1 for char, 2 for short, etc).Try to waste as little space as possible
In this way, we try to use some waste space to improve the speed of memory access.
So in your codes, it meams that
#include <stdio.h>
#include <stdlib.h>
struct // the base address is &a
{
int m; // [0, 4)
int s; // [4, 8)
int l; // [8, 12)
union
{
char c[10]; // [12, 22)
};
// char m_align[2] // there are 4 byte for align
float p; // [24, 28)
}a; // sizeof = 28
the value m is begin at the start of type a, and occupancy 4 byte in 32bit system, so it's address is [0, 4). and it's start address can divisible by sizeof(int).
this is the same to s and l.
and then the union value c[10] occupancy, occupancy [12, 22), the begining od it's address 12 can divisible by sizeof(int).
What's importment the next address is 22, and the value p will occupancy sizeof(float) = 4 bytes,but the address 22 can't divisible by sizeof(float). we must fill the space to alignment the struct and try to waste as little space as possible. So the base address of value p will be 24 which can divisible by sizeof(float), so the adddress of p is [24, 28]...
you can see this https://en.wikipedia.org/wiki/Data_structure_alignment for detail
The members in the structure arranged as a group of 4 bytes in 32 bit processor.So you are getting 28 bytes as size.
for more details see here
It is due to padding
typedef struct structA
{
char C;
double D;
int I;
} structA_t;
Size of this structA_t structure:
sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) = 1 + 7 +
8 + 4 = 20 bytes
But this is wrong , the correct is
24
. Why?
There is most likely 4 byte padding after the last ìnt.
If sizeof(double) == 8 then likely alignof(double) == 8 also on your platform.
Consider this situation:
structA_t array[2];
If size would be only 20, then array[1].D would be misaligned (address would be divisible by 4, not 8 which is required alignment).
char = 1 byte
double = 8 bytes
int = 4 bytes
align to double =>
padding char => 1+7
padding double => 8+0
padding int => 4+4
=> 24 bytes
or, simply put, is the multiple of the largest => 3 (the number of fields) * 8 (the size of the largest) = 24
my guess would be the size of int in your system is 4 Bytes, so the int must also be padded by 4 Bytes in order to achieve a word size of 8 Bytes.
total_size=sizeof(char) + 7 Byte padding + sizeof(double) + sizeof(int) + 4 Bytes padding = 24 Bytes
Good article on padding/alignment:
http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649
Because of the double member it forces everything to be eight byte aligned.
If you want a smaller structure then following structure gives you 16 bytes only!
typedef struct structA
{
int I;
char C;
double D;
} structA_t;
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 9 years ago.
I am getting 56 bytes for the following. Can anyone explain how is that?
#include <stdio.h>
typedef struct how_many_bytes {
long s[4];
char c, e;
int i[2];
char *d;
} How_Many_Bytes;
int main(){
printf("%lu ", sizeof(How_Many_Bytes));
}
Shouldn't it be (4*8) + 1 + 1 + 2(for padding) + 4 + 4 + 8 = 52 bytes
Because it's a 64-bit machine, so the padding is 6 instead of 2 in your calculation.
Also, you should use %zu to print size_t.
Your analysis is correct, except that there is an additional 4 bytes padding before the char *d member. This is so that the d member is aligned on an 8-byte boundary.
The pahole output for this structure on x86-64 is:
struct how_many_bytes {
long int s[4]; /* 0 32 */
char c; /* 32 1 */
char e; /* 33 1 */
/* XXX 2 bytes hole, try to pack */
int i[2]; /* 36 8 */
/* XXX 4 bytes hole, try to pack */
char * d; /* 48 8 */
/* size: 56, cachelines: 1 */
/* sum members: 50, holes: 2, sum holes: 6 */
/* last cacheline: 56 bytes */
}; /* definitions: 1 */
No matter how you rearrange the members of this structure, you won't be able to do better than 6 bytes in total of padding. The sum of the sizes of the members is 50 bytes, and the maximum alignment of the structure members is 8, so even if you arrange the members in the optimal order there will be 6 bytes of padding at the end of the structure to round its size up to the next biggest multiple of 8.
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.