waynewingorc
waynewingorc

Reputation: 209

Space occupied by array of struct

A question I have on Problem 3.44 of the book Computer Systems: A Programmer's Perspective (3rd edition (6 October 2015)) on data alignment.

The problem:

For each of the following structure declarations, determine the offset of each feild, the total size of the structure, for 8-bit alignment:

struct P1 {short i; int c; int *j; short *d}
...
struct P4 {char w[16]; char *c[2]}
struct P5 {struct P4 a[2]; struct P1 t}

Answer given in the book:

i c j d total
0 2 6 14 16
w c total
0 16 32
a t total
0 24 40

What I don't get is why did struct P4 a[2] in P5 only takes 24 bytes?
Since P5.a is an array of P4 of size 2, shouldn't it occupy 2 * 32 (total size of P4) bytes?


To make sure I quote the book correctly, attaching the screenshots below: enter image description here enter image description here

Upvotes: 0

Views: 124

Answers (3)

recreant
recreant

Reputation: 51

You have a copy of the Global Edition of CS:APP3e.

As we state in the errata web page:

Note on the Global Edition: Unfortunately, the publisher arranged for the generation of a different set of practice and homework problems in the global edition. The person doing this didn't do a very good job, and so these problems and their solutions have many errors. We have not created an errata for this edition.

This is one of the many problems that got messed up.

Upvotes: 5

CGi03
CGi03

Reputation: 650

A code to test: (Gives the occupation in structure, not the size).

#include <stdio.h>

struct P1
{
    short i;
    int c;
    int *j;
    short *d;
    long long end[];
};

struct P4
{
    char w[16];
    char *c[2];
    long long end[];
};

struct P5
{
    struct P4 a[2];
    struct P1 t;
    long long end[];
};

int main(void)
{
    struct P1 p1;
    printf("size of p1 : %zu\n", sizeof(p1));    
    printf("short i : %zu\n", (size_t)&p1.c - (size_t)&p1.i);
    printf("int c : %zu\n", (size_t)&p1.j - (size_t)&p1.c);
    printf("int *j : %zu\n", (size_t)&p1.d - (size_t)&p1.j);
    printf("short *d : %zu\n", (size_t)&p1.end - (size_t)&p1.d);

    struct P4 p4;
    printf("\nsize of p4 : %zu\n", sizeof(p4));
    printf("char w[16] : %zu\n", (size_t)&p4.c - (size_t)&p4.w);
    printf("char *c[2] : %zu\n", (size_t)&p4.end - (size_t)&p4.c);

    struct P5 p5;
    printf("\nsize of p5 : %zu\n", sizeof(p5));
    printf("struct P4 a[2] : %zu\n", (size_t)&p5.t - (size_t)&p5.a);
    printf("struct P1 t : %zu\n", (size_t)&p5.end - (size_t)&p5.t);

    return 0;
}
  • The flexible member array is just to mark the end.

Following Gerhardh's remark, code with offsetof.

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

struct P1
{
    short i;
    int c;
    int *j;
    short d;
    long long end[];
};

int main(void)
{
    struct P1 p1;
    printf("                   Offset        Size    Occupation\n");
    printf("short i  : %12zu %12zu %12zu\n", offsetof(struct P1, i), sizeof(p1.i), offsetof(struct P1, c));
    printf("int c    : %12zu %12zu %12zu\n", offsetof(struct P1, c), sizeof(p1.c), offsetof(struct P1, j)-offsetof(struct P1, c));
    printf("int *j   : %12zu %12zu %12zu\n", offsetof(struct P1, j), sizeof(p1.j), offsetof(struct P1, d)-offsetof(struct P1, j));
    printf("short *d : %12zu %12zu %12zu\n", offsetof(struct P1, d), sizeof(p1.d), offsetof(struct P1, end)-offsetof(struct P1, d));
    printf("end      : %12zu \n", offsetof(struct P1, end));
    return 0;
}

Upvotes: 0

Lundin
Lundin

Reputation: 213296

  • P1 is wrong. In case int* j occupies 8 bytes, then on any known real-world computer with 64 bit addressing, short* d will also occupy 8 bytes. For a total of 22 bytes, assuming no padding was inserted after i, which is unlikely. In case padding is inserted, the total size would be 24 bytes.

    On a real-world 64 bit system, the struct layout would be:

    short  i  size: 2   offset:  0
    int    c  size: 4   offset:  4
    int*   j  size: 8   offset:  8
    short* d  size: 8   offset: 16
    
  • What I don't get is why did struct P4 a[2] in P5 only takes 24 bytes?

    It doesn't. P4 = 32 bytes, no padding. 2 * 32 = 64 bytes. P5 will be 64 + 24 = 88 bytes.

If you are quoting the book correctly, then evidently it has not been proof-read from the programmer's perspective...

Upvotes: 2

Related Questions