-3

I have written simple C code to find structure size and I don't how the memory is allocated.

struct s {
    long e;
    char c;
    float f;
    char d;
};

int main() {
    struct s a;
    printf("%d", sizeof(a));
    return 0;
}

Output: 24

Kindly explain me, How the output came? your help is appreciated. Thanks

mmixLinus
  • 1,646
  • 2
  • 11
  • 16
Gireesh B
  • 11
  • 2
  • OT: `printf("%d", sizeof(a));` --> `printf("%zu", sizeof(a));` – Support Ukraine Feb 24 '23 at 11:13
  • 1
    The topic you are looking for is packing/padding/alignment, example discussion: https://stackoverflow.com/questions/4306186/structure-padding-and-packing (there are lots more if you search the keywords) – teapot418 Feb 24 '23 at 11:16
  • 1
    You can also explore the details using `offsetof` as shown in https://stackoverflow.com/a/56877779/21105992 – teapot418 Feb 24 '23 at 11:19

1 Answers1

4

Your code might actually have undefined behavior as you pass a value of type size_t where printf expects an int for %d. If int and size_t have a different representation, as is the case on most 64-bit systems, the code has undefined behavior and the output might be totally meaningless. You should use %zu or cast the argument as (int)sizeof(a).

In your case, the systems reports a structure size of 24 bytes, which is more than the combined sizes of the members because of padding. The C compiler inserts padding bytes between some of the members and possibly at the end of the structure to ensure that each member is stored at a memory address corresponding to its alignment requirements.

Here is how it works:

  • long e; is 8 bytes and requires 8 byte alignment. offset is 0
  • char c; is 1 byte, no alignment, offset is 8
  • float f; is 4 bytes and 4 byte alignment, therefore 3 padding bytes are inserted between c and f, offset is 12
  • char d; is 1 byte, no alignment, offset is 16
  • 7 padding bytes are inserted at the end of the structure to make its length a multiple of the largest alignment, hence 8 bytes.

The total size of the structure is 24 bytes, as reported.

You could reduce the overhead size by changing the order of fields, moving d before f or f before c.

Here is a modified version:

#include <stdio.h>

struct s1 {
    long e;   // offset  0, size 8, bytes [0..7]
    char c;   // offset  8, size 1, byte  [8]
              // 3 padding bytes          [9..11]
    float f;  // offset 12, size 4, bytes [12..15]
    char d;   // offset 16, size 1, byte  [16]
              // 7 padding bytes          [17..23]
};

struct s2 {
    long e;   // offset  0, size 8, bytes [0..7]
    float f;  // offset  8, size 4, bytes [8..11]
    char c;   // offset 12, size 1, byte  [12]
    char d;   // offset 13, size 1, byte  [13]
              // 2 padding bytes          [14..15]
};

int main(void) {
    struct s1 a;
    struct s2 b;
    printf("%zu %zu\n", sizeof(a), sizeof(b)); // prints 24 16
    return 0;
}

Note however that the size and alignment requirements for standard types short, int, long, float and double vary from one architecture to another. Your program and the one above would produce different output on Windows systems.

chqrlie
  • 131,814
  • 10
  • 121
  • 189