0

I have some structs for which i am checking their sizes. According to the rules of padding, i am expecting different results. When i have a char of size between 4 and 8, i see that padding is applied to the char up to size 8, but padding is not applied for the preceding integer or for the last integer/variable of the struct.

The main question here is why padding is not applied to integers whenever they are followed by char of size bigger than 4?

What is the meaning of applying padding to the char to reach 8 bytes, if integer still use 4 bytes?

Below, you can see the code why my questions in comments:

#include <stdio.h>

typedef struct {
    int i;      
    char str[3]; //padding of 1
    int f;
} stru_10;

//size is 4+4+4 = 12

typedef struct {
    int i;       //why no padding applied here?
    char str[7]; // padding of one
    int f;       //why no padding applied here?
} stru_11;

//Actual result : size is 16. Why no padding on integers?

typedef struct {
    int i;       //why no padding applied here?
    char str[9]; // padding of 3
    int f;       //why no padding applied here?
} stru_12;

//Actual result : Size is 20. Why no padding on integers?

typedef struct {
    int i;        //why no padding applied here?
    char str[5];  // padding of 3
    int f;        //why no padding applied here?
} stru_13;

//Actual result : Size is 16. Why no padding on integers?

typedef struct {
    int i;        
    char c;  // padding of 3
    int f;        
} stru_14;

//Actual result. Size is 12 as expected.

typedef struct {
    int i;    // padding of 4    
    char *c;  // padding of 3
    int f;    //padding of 4  
} stru_15;

//Actual result. Size is 24 as expected(8*3).

int main(void) {

    printf("Size of stru_10 is %d\n",sizeof(stru_10)); //12
    printf("Size of stru_11 is %d\n",sizeof(stru_11)); //16
    printf("Size of stru_12 is %d\n",sizeof(stru_12)); //20
    printf("Size of stru_13 is %d\n",sizeof(stru_13)); //16
    printf("Size of stru_14 is %d\n",sizeof(stru_14)); //12
    printf("Size of stru_15 is %d\n",sizeof(stru_15)); //24

    return 0;
}
sreepurna
  • 1,562
  • 2
  • 17
  • 32
Dchris
  • 2,867
  • 10
  • 42
  • 73
  • 1
    Perhaps you should ask yourself, what is the purpose and benefit of padding. You can google that, and then the reason might be clear to you. Read [this answer to a similar question](http://stackoverflow.com/a/4306269/1983495) – Iharob Al Asimi Mar 03 '17 at 10:23
  • @IharobAlAsimi I have read this similar question before asking here. – Dchris Mar 03 '17 at 11:51
  • Your view at padding seems wrong. Padding will only be applied *before* a struct item. No need to look at any followers of it. I.e.: assume, integer items have to start at an even memory address. If you only have integers, there will be no padding. If you insert *any* item with odd size (char[1], char[3]), the next following integer would not get an even memory address, so there will be a padding byte inserted and the next integer gets an even adress. This is a 'mod 2' sample. In reality, items may need a mod-4 or mod-8 even address. – Holger Mar 03 '17 at 12:04

1 Answers1

1

but padding is not applied for the preceding integer or for the last integer/variable of the struct.

Why would it be?

Don't think of it as "padding". What's going on in most cases is this:

Fundamental data types (ints, floats, doubles, etc.) need to be properly aligned in memory so that the CPU can read them efficiently (or even at all since certain CPUs will just crash your program when you're reading data that isn't correctly aligned). This applies even if they are part of a struct. To achieve that alignment almost everyone follows this model:

  • each struct member is aligned within the struct on their natural alignment.
  • the size of the struct is rounded up to be a multiple of the required alignment of its most strictly aligned member.
  • the alignment of an array is the same as the alignment of its elements.

The C standard allows for much more than this, but in practice this is what pretty much everyone does because it solves all problems of alignment for all data types, structs and arrays of structs. Unless you have a really weird CPU.

In your examples, the alignment requirement for int is most likely 4 and 1 for char. From the above rules you can figure out how the elements will be laid out. What you call "padding" is just the bits that are left over when things are properly aligned.

Let's take one of your examples.

typedef struct {
    int i;       //why no padding applied here?
    char str[7]; // padding of one
    int f;       //why no padding applied here?
} stru_11;

i needs to be aligned at 4. It is at offset 0. (0 % 4) == 0, so the alignment is good. str needs to be aligned at 1. The first free offset in the struct is 4. (4 % 1) == 0, so that's good enough. str is put at offset 4. f needs to be aligned at 4, the first free offset in the struct is 11. (11 % 4) == 3, so that's not good enough. But 12 is good enough, let's put f at 12. The size of the struct is now 16 and the alignment of the largest member of the struct is 4, (16 % 4) == 0, that fullfils all the requirements of struct member alignment, we can leave the struct as size 16, no further alignment or padding necessary.

Please note that what I wrote above is not mandated by the language standard. The mechanism for laying out struct members is part of other standards that are called ABI (application binary interface) and each operating system + CPU combo can have their own ABI. Most ABIs define things to be done like this because it's the easiest and most efficient way of doing it, but in case of doubt you need to find the particular documentation from your OS+CPU combo (if it exists at all).

Art
  • 19,807
  • 1
  • 34
  • 60
  • 1
    @Dchris Just a clarification. What I wrote is not mandated by the language standard. The mechanism for laying out struct members is part of other standards that are called ABI (application binary interface) and each operating system + CPU combo can have its own ABI. Most ABIs define things to be done like this, but in case of doubt you need to find the particular documentation from your OS+CPU combo (if it exists at all). – Art Mar 03 '17 at 12:28