2

I have read that characters are a special case, they are equally expensive from anywhere they live inside a single machine word, hence they don't have preferred alignment.

According to the above statement the size of both Struct_1 and Struct_2 should be 5 bytes. The Struct_1 is occupying 5 bytes as per the expectation but the Struct_2 is occupying 8 bytes.

Please explain me the reason behind this.

Going further I have printed the address of the individual members inside the Struct_2. It confirms that padding space is being added after the last member char g.

Why is padding required at the end of the last member?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Struct_1 {
    char a;
    char b;
    char c;
    char d;
    char e;
} Struct_1;

typedef struct Struct_2 {
    int  f;
    char g;
} Struct_2;

int main(void) {
    Struct_2 strc2;

    printf("\tsizeof(Struct_1): %ld\n", sizeof(Struct_1));
    printf("\tsizeof(Struct_2): %ld\n", sizeof(Struct_2));

    printf("\tsizeof(strc2.f) : %ld\n\n", sizeof(strc2.f));

    printf("\t&(strc2.f) = %p\n", &(strc2.f));
    printf("\t&(strc2.g) = %p\n", &(strc2.g));

    return (0);
}

Output of the above code:

sizeof(Struct_1): 5 
sizeof(Struct_2): 8 
sizeof(strc2.f) : 4 

&(strc2.f) = 0x7ffe07b08c50 
&(strc2.g) = 0x7ffe07b08c54
chqrlie
  • 131,814
  • 10
  • 121
  • 189
SRIKANTH
  • 65
  • 7

3 Answers3

6

structures also have to be aligned according to the size of the biggest element (int here). Keep in mind that you can have an array of structures, so every element has to be aligned considering the element having the largest size.

Consider consecutive Struct_2 in memory.

100 f1
101 f2
102 f3
103 f4
104 g1
105 padding since f has to be aligned at an address divisible by 4
106 padding since f has to be aligned at an address divisible by 4
107 padding since f has to be aligned at an address divisible by 4
108 f1
......
Gaurav Sehgal
  • 7,422
  • 2
  • 18
  • 34
  • Could you please explain or share the source which explains why the structures have to be aligned according to the size of the biggest element. – SRIKANTH Aug 09 '19 at 09:50
  • GCC knows an attribute "packed" that can be used to disable padding (perhaps only on some target archtecitures). You use it like `typedef struct Struct_3 { int f; char g; } __attribute__((packed)) Struct_3;`. – the busybee Aug 09 '19 at 10:08
  • Structures do not have to be aligned according to the size of the biggest member. For example, in `struct { int x; char y[9]; }`, `y` is the biggest member, with size nine bytes, but the structure does not have to be aligned to a multiple of nine bytes. In common C implementations, it would need four-byte alignment for the `int`. Members might also be other structs or unions with large sizes but lax alignment requirements. In addition to these aggregate members, a member might be a basic type such as `long double` that has a large size but a lax alignment requirement. – Eric Postpischil Aug 09 '19 at 10:24
  • Note that “element” is commonly used for the subobjects in arrays, while “member” is commonly used for the subobjects in structures. – Eric Postpischil Aug 09 '19 at 10:25
  • @thebusybee *GCC knows an attribute "packed" that can be used to disable padding* That is a **dangerous** option. It can result in code that fails to run on platforms that actually enforce alignment. For example: `someFunction( double *addressOfDouble )` can fail or crash your process if called with `someFunction( &(packedStruct.doubleVal) );` because the `packedStruct.doubleVal` is not a properly aligned `double`. See https://stackoverflow.com/questions/8568432/is-gccs-attribute-packed-pragma-pack-unsafe – Andrew Henle Aug 09 '19 at 13:55
  • @Andrew you're perfectly right, I should have mentioned that. There are so many ways to shoot yourself in the foot. – the busybee Aug 09 '19 at 14:03
4

On your system, it appears an int occupies four bytes of memory, and every int must be aligned on a 4-byte boundary (i.e. its address must be a multiple of 4).

Such an alignment is required on quite a few systems, to ensure operations work efficiently - if an int is not aligned properly, the behaviour varies between systems. For example, on quite a few systems, it results in a hardware trap, which is handled by the operating system, which either causes the program to run slowly or be terminated abnormally.

The padding is required to ensure that all members of the struct are properly aligned, and that must also be true for an array of such a struct.

This means, if you have an array of two (or more) struct Struct_2, such as

struct Struct_2 x[2];

then the int members of both x[0] and x[1] must be aligned on a 4-byte boundary.

The only way this can be true is if there is 4, or a multiple of 4, bytes between x[0].f and x[1].f. However, x[0].g only occupies one byte. That means, to ensure x[0].f and x[1].f are both aligned on a 4-byte boundary there is a need for 3 additional padding bytes so the space between x[0].f and x[1].f occupies four bytes.

If a structure contains members of different sizes, then they must all be properly aligned.

In the above, for ease of discussion, I've assumed the size and alignment of an int is 4. In general, size and therefore alignment of an int are implementation-defined.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

The C standard requires it.

N1570 6.2.8 Alignment of objects

1 Complete object types have alignment requirements which place restrictions on the addresses at which objects of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. [snip]

4 Alignments are represented as values of the type size_t. Valid alignments include only those values returned by an _Alignof expression for fundamental types, plus an additional implementation-defined set of values, which may be empty. Every valid alignment value shall be a nonnegative integral power of two.

Furthermore, the alignment of char, unsigned char, and signed char have the weakest alignment type so they will be padded in a manner defined by the implementation. Your target platform requires it. This is especially true when dealing with structures of mixed types.

QwazyWabbit
  • 149
  • 2
  • 6