-1

So I have a struct in C defined as so:

struct example {
  int ex1;
  u_long ex2;
  float ex3;
  float ex4;
};

So the size of all of example's member is 20, but the size of example is 24 which means padding is being added. What I don't really understand is why and where.

Excuse me if my terminology is incorrect, but I thought that since it was 4 byte clean (i.e. size of all members % 4 == 0 ) that padding wouldn't need to be added. Is it because I am running an x86 that it needs to be 8 byte clean, or is that just the norm?

Then I don't really know where the padding is being added, I would assume around the u_long but I don't know for sure.

Phenom588
  • 81
  • 1
  • 8
  • 1
    You could use the [`offsetof`](http://en.cppreference.com/w/c/types/offsetof) macro to find out. – Some programmer dude Jan 08 '16 at 18:35
  • 1
    None of the types has a well-defined size. And you might get additional padding between the fields. – too honest for this site Jan 08 '16 at 18:55
  • Thanks @JoachimPileborg! I ended up using the suggestion here http://stackoverflow.com/questions/9788679/how-to-get-the-relative-adress-of-a-field-in-a-structure-dump-c because I was lazy but I didn't know that macro existed. – Phenom588 Jan 08 '16 at 18:56

3 Answers3

3

Structs are also usually padded at the end, so that the total size of the struct is evenly divisible by the required alignment of the member with the greatest alignment.

In your case, u_long requires an alignment of 8 bytes and it is put 4 bytes after the end of the first member, so that its address is on an 8-byte boundary. The total size of the struct becomes 24, so it doesn't need any additional padding at the end.

Padding at the end makes sure that, when laid out in a sequential array, the second element doesn't break the alignment of some of the members.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • 2
    or possibly it is before u_long so that it is aligned on an 8-byte boundary – John Hascall Jan 08 '16 at 18:39
  • @JohnHascall: that is certainly the case with the example, I just failed to do the math :-) – Blagovest Buyukliev Jan 08 '16 at 18:47
  • Alright I see, so its the highest alignment required by the members of the structure that decides the alignment of the structure then. I checked in gdb (thanks to http://stackoverflow.com/questions/9788679/how-to-get-the-relative-adress-of-a-field-in-a-structure-dump-c) and the padding is at the end. Thank you! – Phenom588 Jan 08 '16 at 18:50
  • "Structs are also usually padded at the end". Is incorrect. There can be (and are) padding bytes added whereever needed to have proper alignment. Only exception is before the first member. – too honest for this site Jan 08 '16 at 18:59
  • @Olaf: you are right that decisions on padding are entirely up to the implementation and the language specification doesn't mandate much of it, but most "traditional" implementations on mainstream platforms do what I've described. Code shouldn't be designed to assume a certain layout, but it is good to know the reasons why the compiler did something. – Blagovest Buyukliev Jan 08 '16 at 19:04
  • I agree it is good tro know the hows & whys - that was not my point. I disagree about just(!) padding at the end. typical implementations add padding within a `struct` as well to align each field. Array padding follows from this. – too honest for this site Jan 08 '16 at 19:31
1

I thought that since it was 4 byte clean (i.e. size of all members % 4 == 0 ) that padding wouldn't need to be added.

That is not a safe assumption. C places few restrictions on how much padding can be added to a struct representation, or where. It says nothing at all about when or why. These choices are up to the compiler.

Is it because I am running an x86 that it needs to be 8 byte clean, or is that just the norm?

You are presuming that being "8-byte clean" has anything to do with the padding. It might do, but again, that's an implementation decision.

Generally speaking, compilers insert padding to ensure that all members can be aligned for optimal access in every element of an array of structs. That may require padding either between members or at the end or both. But that's still an implementation consideration. If you want to know about how the particular C implementation you are using approaches the issue, then you need to consult its documentation.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Here is a test, run on one particular machine, your results may vary:

$ cat ul.c
#include <stdio.h>

struct example {
  int ex1;
  unsigned long ex2;
  float ex3;
  float ex4;
};

struct example ex;

int main ( void ) {
        printf("Size:\t%zd\n", sizeof(ex));
        printf("ex @\t%p\n", &ex);
        printf("ex1 @\t%p\n", &ex.ex1);
        printf("ex2 @\t%p\n", &ex.ex2);
        printf("ex3 @\t%p\n", &ex.ex3);
        printf("ex4 @\t%p\n", &ex.ex4);
        return 0;
}

$ ./ul
Size:   24
ex @    0x600940
ex1 @   0x600940
ex2 @   0x600948
ex3 @   0x600950
ex4 @   0x600954

The padding is between ex1 and ex2 here.

John Hascall
  • 9,176
  • 6
  • 48
  • 72