#include‬ <stdio.h>
struct test
{
unsigned int x;
long int y;
unsigned int z;
};
int main()
{
struct test t;
unsigned int *ptr1 = &t.x;
unsigned int *ptr2 = &t.z;
printf("%d", ptr2 - ptr1);
return 0;
}
This program's output is 4 on my system, why do I get this result instead of 2?
Is the ptr2 - ptr1 statement correct as ptr1 and ptr2 come from pointers to members of the same structure item?
The reason this outputs 4 has to do with the size of each type and struct padding and alignment.
On my system, sizeof(unsigned int) is 4, sizeof(long int) is 8, and sizeof(struct test) is 24. So to ensure that the 64-bit field lies on a 64-bit boundary, the structure is physically laid out like this:
struct test
{
unsigned int x; // 4 bytes
// 4 bytes padding
long int y; // 8 bytes
unsigned int z; // 4 bytes
// 4 bytes padding
};
So when you take the difference between the offset of x and the offset of z, there are 16 bytes difference. And since we're doing pointer subtraction, the value of the difference is {byte offset difference} / {element size}. So we have 16 (byte difference) / 4 (sizeof(unsigned int)) == 4.
If sizeof(long int) was 4, then the struct would probably be laid out like this:
struct test
{
unsigned int x; // 4 bytes
long int y; // 4 bytes
unsigned int z; // 4 bytes
};
In which case the output would be 2.
Note that while the ordering of struct members is defined to be sequential, the layout of the padding is is implementation defined. Compilers are free to pad as they see fit.
From section 6.7.2.1 of the C standard:
13 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that
increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial
member (or if that member is a bit-field, then to the unit
in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
...
15 There may be unnamed padding at the end of a structure or union.
Related
I already referred to this question, but still can't find an answer for this following case.
Why does the padding not apply for the case of test1?
#include <stdio.h>
typedef unsigned short u16;
typedef unsigned char u8;
typedef struct
{
u8 a[5];
u8 b;
u8 c;
} test1;
typedef struct
{
u8 a[5];
u16 b;
} test2;
int main(void) {
test1 t1;
test2 t2;
printf("t1 = %d\n", sizeof(t1));
printf("t2 = %d\n", sizeof(t2));
return 0;
}
Output:
t1 = 7
t2 = 8
Update
After the answers from #ryyker and #Ajay Brahmakshatriya, i made another test code and it seems the answers don't apply to this case... If the padding size is 3, because the size of type test1 is 3, why does the size of test2 not 9 instead of 7?
#include <stdio.h>
typedef unsigned short u16;
typedef unsigned char u8;
typedef struct
{
u8 a;
u8 b;
u8 c;
} test1;
typedef struct
{
test1 a[2];
u8 b;
} test2;
int main(void) {
test1 t1;
test2 t2;
printf("t1 = %d\n", sizeof(t1));
printf("t2 = %d\n", sizeof(t2));
return 0;
}
Output:
t1 = 3
t2 = 7
The alignment requirement of a struct is greater than equal to the alignment requirement of each its member. Also, the alignment requirement of an array is the same as that of its elements.
If the alignment requirement of u8 is 1 byte and the alignment requirement of u16 is 2 bytes, the alignment requirement of test1 would be at least 1 byte and that of test2 would be at least 2 bytes.
Since the alignment requirement of test2 is 2 bytes, its size should also be a multiple of 2 bytes (this way if you declare an array of the struct, all the elements of the array can be aligned properly).
The sum of sizes of elements of test2 is 7 bytes. The closest multiple of 2 is 8 bytes.
For test1, since the alignment requirement is only 1 byte, 7 is an acceptable size.
Finally, the implementations are allowed to add any amount of padding to the structs as long it satisfies all the above constraints. So there is no right way to answer the question "Why is the size of this struct not equal to what I calculated?". What I have here is a likely rationale as to why your implementation chose the current sizes.
Why does the padding not apply for the case of test1... Because bytes are the smallest natural memory segment, and in the case of the first struct the only type used, the compiler sets memory alignment for this struct at one byte segments. None of the members bump up against that natural alignment. Therefore padding is not required.
In the second struct definition there is one u16 type, and an odd number of bytes (5) stored in the array member. The u16 member causes alignment boundaries ( | ) to be (by default) two bytes:
The first struct could be viewed as a series of byte memory locations, with 1 byte alignment:
|.......|.......|.......|.......|.......|.......|.......| ( 7-bytes )
a[0] a[1] a[2] a[3] a[4] b c
The second struct, with the u16 member, uses 2-byte alignment: (thus also results in padding.)
|...............|...............|...............|..............| (8-bytes )
a[0] a[1] a[2] a[3] a[4] (padding) b
Note, default alignment boundaries can be modified by using a pragma statement. For example pragma pack(1) forces the alignment boundary to 1 byte. This would effectively place b adjacent to a[4] in memory, and would make the second struct the same size as the first.
|.......|.......|.......|.......|.......|.......|.......| ( 7-bytes )
a[0] a[1] a[2] a[3] a[4] b
pragma pack(1)//force alignment to 1 byte
typedef struct
{
u8 a[5];
u16 b;
} test2;
pragma pack()// set packing back to what it was
Even though this question/answer talks about pragma statements, it covers the surrounding concepts, such as the one you are asking about well.
Here is a snippet:
struct a {
float* f;
char c;
int i;
char z[4];
double d;
short s;
};
struct b {
struct a a1;
int j;
struct a a2;
};
When I do a printf("%d\n",sizeof(struct a)), it emits to me 32... But when I do the same for the struct b, it emits 72 which I don't know how can be possible this, it should be 32+4+28(padding)+32 following the same calcs that I did to find out the previous result... can anyone tell me why is this happening?
From my calculations, struct a requires 26 bytes (including padding in the middle) + 6 bytes at the end. It looks something like this:
struct a {
float* f; // takes 4 bytes
char c; // takes 1 bytes + 3 padding
int I; // takes 4 bytes
char z[4]; // takes 4 bytes
double d; // takes 8 bytes, sets a requirement for memory alignment
short s; // takes 2 bytes.
// here there are 6 more bytes for padding required for array alignment.
};
The double in the struct means that struct a must be positioned on an 8 byte alignment mark, so that the double is correctly aligned.
Now, when we have struct b, we have:
struct b {
struct a a1; // takes 32 bytes, REQUIRES and 8 byte alignment
int j; // takes 4 bytes + 4 byte padding (for alignment).
struct a a2; // takes 32 bytes, MUST start on an 8 byte alignment
};
I hope this wasn't homework or something... :-p
Nothing is aligned to more than multiples of 8 for the x86/amd64 architectures. See for example Structure Alignment for Visual Studio. struct a and struct b have a double member, so they must be aligned at a multiple of 8 and their sizeof must be a multiple of 8; you can easily see why 32 is correct for struct a. The int j is 4 bytes, at a multiple of 4; since it comes immediately after struct a a1 it need no padding, being placed a multiple of 8. struct a a2 needs to be at a multiple of 8, so 4 bytes of padding are added. Overall, struct b needs 32 bytes for member a1, 4 bytes for member j, 4 bytes of padding (to bring a2 to a multiple of 8) and 32 for member a2 for a total of 72.
This question already has answers here:
Why is padding added for multiple data members of structures and not for single members?
(4 answers)
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 8 years ago.
Am trying to understanding the struct padding.
The below struct is padded:
struct s {
int j;
char c;
int i;
};
==> sizeof(struct s) = 12
But for this struct it is not padding. why?
struct s {
char c;
}
==> sizeof(struct s) = 1
OR
struct s {
short int i;
}
==> sizeof(struct s) = 2
Why the padding is not applicable for the above two structs?
Padding is done to keep members of the struct aligned, so that access is fast.(*) Consider what happens in an array of structs:
struct s {
int i;
char c;
};
struct s a[0];
If this struct were not padded, a[1] would have the address (char *)a + 5. That's unaligned, assuming a[0] is aligned. Therefore, the struct will typically be padded to a multiple of sizeof(int). (Were i a long long, then the whole struct would be padded to a multiple of sizeof(long long); try and see.)
With a single char, there's no need to pad because the char will be aligned anyway, while there are no other members that become unaligned. With a single short, an alignment of 2 is sufficient to keep the single member aligned, always.
(*) On some CPUs, but not Intel x86-compatible ones, unaligned access can actually crash your program.
The padding is added to make sure that the int member i is aligned.
Assuming that your int is 4 bytes in size, then it will be placed on a 4 byte boundary to align it. That means that there are 3 bytes of padding after the char. The size of 12 is therefore quite reasonable.
Imagine if there was no padding. Then the offsets would be:
Member Offset
j 0
c 4
i 5
If the struct was laid out this way then i would be mis-aligned. To place it on a 4 byte boundary, it needs to be at offset 8. Hence the 3 bytes of padding, and the total size of 12. So, the actual layout is:
Member Offset
j 0
c 4
<padding> 5
i 8
I am working with structs in c on linux.
I started using bit fields and the "packed" attribute and I came across a wierd behavior:
struct __attribute__((packed)) {
int a:12;
int b:32;
int c:4;
} t1;
struct __attribute__((packed)) {
int a:12;
int b;
int c:4;
}t2;
void main()
{
printf("%d\n",sizeof(t1)); //output - 6
printf("%d\n",sizeof(t2)); //output - 7
}
How come both structures - that are exactly the same - take diffrent number of bytes?
Your structures are not "exactly the same". Your first one has three consecutive bit-fields, the second has one bit-field, an (non bit-field) int, and then a second bit-field.
This is significant: consecutive (non-zero width) bit-fields are merged into a single memory location, while a bit-field followed by a non-bit-field are distinct memory locations.
Your first structure has a single memory location, your second has three. You can take the address of the b member in your second struct, not in your first. Accesses to the b member don't race with accesses the a or c in your second struct, but they do in your first.
Having a non-bit-field (or a zero-length bit-field) right after a bit-field member "closes" it in a sense, what follows will be a different/independent memory location/object. The compiler cannot "pack" your b member inside the bit-field like it does in the first struct.
struct t1 // 6 bytes
{
int a:12; // 0:11
int b:32; // 12:43
int c:4; // 44:47
}__attribute__((packed));
struct t1 // 7 bytes
{
int a:12; // 0:11
int b; // 16:47
int c:4; // 48:51
}__attribute__((packed));
The regular int b must be aligned to a byte boundary. So there is padding before it. If you put c right next to a this padding will no longer be necessary. You should probably do this, as accessing non-byte-aligned integers like int b:32 is slow.
#include<stdio.h>
struct mystruct
{
char cc;
float abc;
};
union sample
{
int a;
float b;
char c;
double d;
struct mystruct s1;
};
int main()
{
union sample u1;
int k;
u1.s1.abc=5.5;
u1.s1.cc='a';
printf("\n%c %f\n",u1.s1.cc,u1.s1.abc);
k=sizeof(union sample);
printf("%d\n\n",k);
return 0;
}
The size of operator is returning 8 I am still able to access the structure elements, more than one at a time and still the sizeof operator is returning the max size of primitive data types i assume. Why is this behavior? Is the size actually allocated is 8? and the sizeof is returning a wrong value? Or is the actual allocated size is 8? Then how is the structure accommodated?? If we allocate an array of unions using malloc and sizeof will it allocate enough space in such case? Please eloborate.
Typically, the size of the union is the size of its biggest member. The biggest member is [likely] your struct member as well as the double member. Both have size 8. So, as sizeof correctly told you, the size of the union is indeed 8.
Why do you find it strange? Why do you call 8 "wrong value"?
struct mystruct
{
char cc; //1 -byte
//3 bytes Added here for Padding
float abc; //size of float is 4-bytes
};
so 1 + 3 + 4 = 8 bytes. We knew the memory will be allocated for largest member of union. In our case both sizeof(double) = sizeof(struct mystruct) is 8.
A union is used to place multiple members at the same memory location - you can't use more than one member at a time. All of them overlap, so the size of the union is the same as the size of the largest member.
Union types are special structures which allow access to the same memory using different type descriptions. one could, for example, describe a union of data types which would allow reading the same data as an integer, a float or a user declared type
union
{
int i;
float f;
struct
{
unsigned int u;
double d;
} s;
} u;
In the above example the total size of u is the size of u.s (which is the sum of the sizes of u.s.u and u.s.d), since s is larger than both i and f. When assigning something to u.i, some parts of u.f may be preserved if u.i is smaller than u.f.