How is sizeof structures found? [duplicate] - c

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.

Related

Bit field in C; bytes and bits [duplicate]

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 2 years ago.
I have found the following example:
#include <stdio.h>
// Space optimized representation of the date
struct date {
// d has value between 1 and 31, so 5 bits
// are sufficient
unsigned int d : 5;
// m has value between 1 and 12, so 4 bits
// are sufficient
unsigned int m : 4;
unsigned int y;
};
int main()
{
printf("Size of date is %lu bytes\n", sizeof(struct date));
struct date dt = { 31, 12, 2014 };
printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
return 0;
}
The results are
Size of date is 8 bytes
Date is 31/12/2014
I cant understand the first result. Why is it 8 bytes?
My thoughts:
y is 4 bytes, d is 5 bits and m is 4 bits. The total is 4 bytes and 9 bits. 1 byte is 8 bits, then the total is 41 bits.
There is a very good explanation here
C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case then some compilers may allow memory overlap for the fields whilst other would store the next field in the next word (see comments on bit fiels portability below).

C Sizeof char[] in struct [closed]

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.

It will give the output 28 on DEV c++ compiler I am expecting 26 considering float as 4 byte int as 4 byte and char as 1 byte [duplicate]

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

Why is struct containing single char not padded to size 4 on a 32-bit system? [duplicate]

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.

Finding the correct size of a misaligned structure

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;

Resources