Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do structures not have padding? [duplicate]

Tags:

c

sizeof(x) returns 2 for the structure below

struct s {
    short c;
} x;

but for the structure

struct s {
    short c;
    char a;
} x;

sizeof(x) returns 4, Why?

The second one gets one padding byte (assuming short is 2 bytes long and char 1 byte long). Shouldn't the first structure have 2 padding bytes then (and thus be 4 bytes long)?

like image 967
user3711671 Avatar asked Feb 14 '19 12:02

user3711671


People also ask

How can structure padding be avoided?

In Structure, sometimes the size of the structure is more than the size of all structures members because of structure padding. Note: But what actual size of all structure member is 13 Bytes. So here total 3 bytes are wasted. So, to avoid structure padding we can use pragma pack as well as an attribute.

Why is structure padding needed?

The answer to that lies in how a CPU accesses memory. Typically a CPU has alignment constraints, e.g. a CPU will access one word at a time, or a CPU will require data to be 16byte aligned, etc. So to make sure that data is aligned according to the constraints of the CPU, padding is required.

What is structure padding why is it required How do you avoid structure padding?

The structural padding is an in-built process that is automatically done by the compiler. Sometimes it required to avoid the structure padding in C as it makes the size of the structure greater than the size of the structure members. We can avoid the structure padding in C in two ways: Using #pragma pack(1) directive.

Why does the compiler sometimes insert padding between fields?

The compiler will insert a padding byte after the char to ensure short int will have an address multiple of 2 (i.e. 2 byte aligned).


2 Answers

The predominant use of padding is to align structure members as required by the hardware (or other aspects of the C implementation). An algorithm for laying out data in a struct is in this answer.

To answer the question in your title, when do structures not have padding: A structure does not require padding for alignment if each member’s alignment requirement is a divisor of the total size of all preceding members and of the total size of all members. (A C implementation may still add padding for reasons other than alignment, but that is a bit unusual.)

For your examples, let’s suppose, in a C implementation, short is two bytes in size and requires two-byte alignment. By definition, char is one byte and requires one-byte alignment.

Then, in struct s {short c;}:

  • c is put at the beginning of the struct. There is never any padding at the beginning.
  • If we make an array of these struct, the next struct s will begin two bytes beyond the first, and its member c will still be at a multiple of two bytes, so it is aligned correctly.
  • Therefore, we do not need any padding to make this work.

In contrast, in struct s {short c; char a;}:

  • c is put at the beginning.
  • a is put two bytes after c. This is fine, since a only requires one-byte alignment.
  • If we do not add any padding, the size of the struct is three bytes. Then, if we make an array of these struct, the next struct s will begin three bytes from the start.
  • In that second struct s, the c member will be at an offset of three bytes. That violates the alignment requirement for short.
  • Therefore, to make this struct work, we must add one byte of padding. This makes the total size four bytes. Then, in an array of these struct, all the members will be at boundaries required by their alignment.

Even if you declare just a single object of a structure, as in struct s {short c; char a;} x;, a structure is always laid out so it can be used in an array.

like image 102
Eric Postpischil Avatar answered Sep 30 '22 08:09

Eric Postpischil


The first structure has one element of size 2 (assuming short has size 2 on your system). It is as good as directly having an array of short directly.

The second structure is a special thing: access to short variables is best done on even addresses. If we hadn't padding, we had the following:

struct s arr[5]; // an array
void * a = arr; // needed to reference it

Then,

  • arr[0].c is at a.
  • arr[0].a is at a + 2 bytes.
  • arr[1].c is at a + 3 bytes (!).
  • arr[1].a is at a + 5 bytes (!).

As it is preferrable to have arr[1].c at an even address, we add padding. Then,

  • arr[1].c is at a + 4 bytes.
  • arr[1].a is at a + 6 bytes.
like image 26
glglgl Avatar answered Sep 30 '22 06:09

glglgl