Tetrau
Tetrau

Reputation: 43

Data Alignment for C struct

There is a problem (3.45) in CS:APP about the byte offsets of all fields in the following struct.

struct {
  int    *a;
  float  b;
  char   c;
  short  d;
  long   e;
  double f;
  int    g;
  char   *h;
} rec;

Here is the answer from the book, which gives c a three bytes padding, d a two bytes padding and g a four bytes padding.

field  size  offset
-----  ----  ------
a      8     0
b      4     8
c      1     12
d      2     16
e      8     24
f      8     32
g      4     40
h      8     48

And here is my solution, which only gives c a one byte padding and g a four bytes padding.

field  size  offset
-----  ----  ------
a      8     0
b      4     8
c      1     12
d      2     14
e      8     16
f      8     24
g      4     32
h      8     40

So, what's the problem with my solution? It seems to fit the alignment rule (edit* the "rule" here is just a simplified concept summaries by myself, It's not completed or general), all object's offset is a multiple of the size of object.

Would be very thankful for any explanation.

Upvotes: 3

Views: 1128

Answers (2)

0___________
0___________

Reputation: 68033

The answer depends on the compiler, platform and compile options. Some examples: enter image description here

https://godbolt.org/z/4tAzB_

The author of the book does not understand the topic I afraid.

Upvotes: 3

Eric Postpischil
Eric Postpischil

Reputation: 224440

Given the sizes of objects shown and alignment rules that say each of these objects must be aligned to a multiple of its size, then, when the structure is laid out with only the padding required for alignment, the offsets should be as shown in Tetrau’s solution. The book solution is incorrect.

The offsets shown in Tetrau’s solution are in fact the offsets produced by Apple LLVM 10.0.1 with Clang 1001.0.46.4 compiling for x86-64; the output from the program below is:

0
8
12
14
16
24
32
40
48
struct foo {
  int    *a;
  float  b;
  char   c;
  short  d;
  long   e;
  double f;
  int    g;
  char   *h;
} rec;


#include <stddef.h>
#include <stdio.h>


int main(void)
{
    printf("%zu\n", offsetof(struct foo, a));
    printf("%zu\n", offsetof(struct foo, b));
    printf("%zu\n", offsetof(struct foo, c));
    printf("%zu\n", offsetof(struct foo, d));
    printf("%zu\n", offsetof(struct foo, e));
    printf("%zu\n", offsetof(struct foo, f));
    printf("%zu\n", offsetof(struct foo, g));
    printf("%zu\n", offsetof(struct foo, h));
    printf("%zu\n", sizeof rec);
}

Note

The rule that an object requires alignment to a multiple of its size is fine for this exercise, but it should be noted it is not a general rule. A machine might have some eight-byte object but have only a bus and other memory access characteristics that are four bytes wide, so it would only care about four-byte alignment at most for any object. Or a structure member might be another structure that is, say, nine bytes in size (such as struct bar { char x[9]; }), but its alignment requirement would not be nine bytes.

Upvotes: 3

Related Questions