2

Could somebody please explain the output of this code?

#include <iostream>
using namespace std;

struct Yo{
    char sex;
    int a;
};

int main() {
    Yo c;
    cout<<sizeof(c.sex);
    cout<<endl<<sizeof(c.a);
    cout<<endl<<sizeof(c);
    return 0;
}

Output: 1 4 8

How is the size of structure 8?

Massimiliano
  • 16,770
  • 10
  • 69
  • 112
Rishikesh Shukla
  • 317
  • 1
  • 12
  • 5
    It's called memory alignment. –  Jan 13 '14 at 16:46
  • 2
    and that is what structure padding is! – Raghu Srikanth Reddy Jan 13 '14 at 16:48
  • 1
    Because of the padding. You can make the size of the structure exact, you should use `#pragma pack()` as said [here at the end](http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding) –  Jan 13 '14 at 16:50
  • See [this question](http://stackoverflow.com/questions/4306186/structure-padding-and-structure-packing) for an example of structure packing. – mpontillo Jan 13 '14 at 16:52
  • See: http://en.wikipedia.org/wiki/Data_structure_alignment It's affected by architecture word size. Size likes to match that boundary. Position also likes to match that boundary. (If you'd looked at pointer to instead of sizeof you'd have seen that also) Some of this can be over-ridden. –  Jan 13 '14 at 17:10

2 Answers2

4

This is memory alignment.

struct Yo{
    char sex;   // Takes up 1 byte + 3 for padding
    int a;      // Takes up 4 bytes
};

The three bytes between sex and a won't be used because the compiler aligns them for better performance. Thus sex ends up using 1 byte of space and the three bytes after the member variable are used as padding to ensure that int a has an address multiple of 4 (it is 4 byte aligned).

Chris Dargis
  • 5,891
  • 4
  • 39
  • 63
1

Because of structure padding (aka memory alignment). The alignment has to be a power of two (C11 makes this explicit in 6.2.8p4 as stated by @KeithThompson) and because the total size of your structure is 5, the nearest multiple of 4 is 8 so it gives 8, also because the alignment has to be a power of two.

You can use #pragma pack to have the exact size.

#pragma pack(push, 1) /* set alignment to 1 byte boundary */
struct A {
    char s;
    int a;
};
#pragma pack(pop) // restore to default

Warning: #pragma pack is not in standard C, nor is the assumption that the structure requires 4-byte alignment. As @KeithThompson stated.

"The size of a type must be a multiple of its alignment, but the size needn't be a power of 2. For example, assuming 4-byte int, a structure like struct { int a, b; char d; } will likely have an alignment of 4 and a size of 12. The size is the nearest multiple of the alignment, not the nearest power of 2." - @KeithThompson

Packing is useful to decrease memory, use it when you have a structure full of integers, fixed char lengths, etc. I do not know if it's good to use with pointers but I do not see it useful when using a pointer (e.g. a void * in the struct).

Read more here

  • The structure size doesn't have to be a power of 2. Here, it's just padding – Doraj Jan 13 '14 at 16:56
  • The alignment has to, sorry. –  Jan 13 '14 at 16:56
  • The answer still seems wrong to me : put the int before the char in the struct and the sizeof will return 5 : you can't find the sizeof of a struct just by knowing the sum of the sizeof each element – Doraj Jan 13 '14 at 17:01
  • sizeof (struct { int a; char s; } ) == 5 and not 8 – Doraj Jan 13 '14 at 17:04
  • What's your point? You still make no sense. 5 is what it's supposed to be after changing memory alignment. –  Jan 13 '14 at 17:05
  • @Doraj: Try it. You will find that in a C implementation in which the size of `struct { char s; int a; }` is 8, the size of `struct { int a; char s; }` is also 8. The implementation pads the end of the struct so that, in an array of them, each of them has the alignment needed for the members in it. – Eric Postpischil Jan 13 '14 at 17:16
  • @user9000: Packing structures in this way is a GCC extension. Many C implementations have some method to pack structures, but the syntax for it may differ. In a question that asks about C generally, without mentioning a specific compiler, you should be clear in answers about what is standard C versus what is an implementation-specific extension. – Eric Postpischil Jan 13 '14 at 17:18
  • @EricPostpischil I thought MSVC also supports that style. Are you sure it's GCC-only? If so, I'll fix it up. –  Jan 13 '14 at 17:26
  • @downvoter, mind explaining the downvote? it was +1... –  Jan 13 '14 at 17:27
  • @user9000: I did not say it was GCC-only. I said it was a GCC extension. That does not preclude other implementations from adopting the same extension. – Eric Postpischil Jan 13 '14 at 17:30
  • @EricPostpischil indeed, i should have written the whole example i had in mind instead of trying to simplify it too much : `struct { char c; int i; char c2; }` will have a sizeof equal to 12 on 32b architectures (which is not a power of 2, and the sum of all sizeof is 6 which is lower than 8). – Doraj Jan 13 '14 at 17:45
  • @Doraj Will have a size of 12 without the packing? I think you misunderstood what Eric was trying to say. It's quite waste of time arguing with you to understand what I wrote, you clearly have no idea what padding is, go learn more about it. I'm not trying to be offensive but this is seriously how it is and you need to know that. –  Jan 13 '14 at 17:49
  • @user9000: i agree my 1st example was completely false (forgot end of struct padding because of arrays), but you should really compile and test the 2nd one i gave. Padding has nothing to do with power of 2, and you can't know the size of a struct just by knowing its "packed" size (as shown in my 2nd example). – Doraj Jan 13 '14 at 19:35
  • Maybe it doesn't have to be, but in GCC, if you put an aligned attribute to something, it requires it to be a power of two. –  Jan 13 '14 at 19:50
  • Your statement "*The alignment has to be a power of two and because the total size of your structure is 5, the nearest power of two is 8, thus it gives 8.*" is misleading. Alignment must be a power of 2 (C11 makes this explicit in 6.2.8p4). The size of a type must be a multiple of its alignment, but the size needn't be a power of 2. For example, assuming 4-byte `int`, a structure like `struct { int a, b; char d; }` will likely have an alignment of 4 and a size of 12. The size is the nearest multiple of the alignment, *not* the nearest power of 2. (They happen to be the same in your example.) – Keith Thompson Jan 17 '14 at 21:29
  • BTW, @Doraj's earlier comments were mistaken, but the latest is perfectly correct. You say you're not trying to be offensive; apparently you can manage it without trying. Your answer should also mention that `#pragma pack` is not standard C; nor is the assumption that the structure requires 4-byte alignment (though the latter does follow from the output the OP showed). – Keith Thompson Jan 17 '14 at 21:31
  • @KeithThompson Correct, however, GCC was throwing out an error when you try to `__attribute__((aligned(X))` where X is not a pow of 2. I blame GCC. However, your explanation seems good enough to prove me wrong, i'll edit my answer mentioning you. –  Jan 17 '14 at 22:13
  • @user9000: The gcc error doesn't contradict anything I said. Alignments must be powers of 2. The size of a type must be a multiple of that type's alignment, but needn't be a power of 2. Your statement that "because the total size of your structure is 5, the nearest power of two is 8, thus it gives 8" is still incorrect; the structure's size is 8 because that's the nearest multiple of 4, not because 8 also happens, coincidentally, to be the next power of 2. – Keith Thompson Jan 17 '14 at 22:28
  • @KeithThompson Fixed now, you happy? btw, Why isn't your name Ken Thompson? –  Jan 18 '14 at 15:08