0

Why does this bitfield have a size of 4?
Is there any way for me to make it have size 2 (as obviously intended in the code below), or is this impossible to do cleanly?

struct S
{
    unsigned short x : 15;
    bool a : 1;
};

int main() { return sizeof(S); }
user541686
  • 205,094
  • 128
  • 528
  • 886
  • 2
    I believe *word* size is 4 bytes (32 bit) in your system and structures are usually word aligned so 2 extra bytes are added for padding. – KBart Feb 07 '13 at 11:09
  • @KBart: Why would the *word* size affect the alignment of `unsigned short`, which is a half-word? `struct T { unsigned short s1, s2; };` certainly doesn't have an alignment of 4, as far as I know! Also, I should note that adding `#pragma pack(1)` decreases the size to 3, but not 2. – user541686 Feb 07 '13 at 11:10
  • it does not affect size of unsigned short, it adds 2 byte for padding as I stated in my edited comment. – KBart Feb 07 '13 at 11:11
  • I am getting output as 2! – Krishnachandra Sharma Feb 07 '13 at 11:12
  • @KBart: I'm 95% sure you're wrong... correct me if I'm wrong, but I believe the alignment of a struct (which determines the padding generated internally) is the largest alignment of any of its members, and does not inherently depend on the word size of the machine in any way. – user541686 Feb 07 '13 at 11:12
  • @Krishna: On what compiler, certainly not Visual Studio, right? o.O – user541686 Feb 07 '13 at 11:13
  • @Mehrdad 2 here in my gcc. You know... MSVC is the devil's compiler, I hate it! – André Puel Feb 07 '13 at 11:17
  • 1
    `#pragma pack(1)` pads _each member_ to the nearest byte, and you have two members, so the size becomes three (two for the first and one for the second). – Some programmer dude Feb 07 '13 at 11:18
  • @Mehrdad see [here](http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing) for examples. Actually all these memory management related things are highly system dependable, so it is no wonder you get different results. – KBart Feb 07 '13 at 11:20
  • @JoachimPileborg: Uhm, by your logic then, so what do you think will be the size of `struct U { bool a: 1; bool b: 1; };`? One byte, or two bytes? – user541686 Feb 07 '13 at 11:20
  • @KBart: I'll take a look, but I'm completely aware it's system-dependent. I'm trying to understand the results I'm getting. – user541686 Feb 07 '13 at 11:20
  • @Mehrdad, looks like this [discussion](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) happened here some time ago, take a look, there is also some great answers including examples. – KBart Feb 07 '13 at 11:23
  • @KBart: Yes, I'm aware what alignment and packing are, but the problem isn't what you think it is. Look at Aniket's answer below. – user541686 Feb 07 '13 at 11:25
  • @Mehrdad I have only explained the first part of your question (why it has size of 4), that's why I didn't post it as a complete answer. The second part (packing) depends on your compiler as *#pragma*s interpretation are not part of a standard. – KBart Feb 07 '13 at 11:28
  • @KBart: That's why no one was talking about the standard to begin with, I don't know why everyone is talking about the standard all of a sudden. The whole discussion has been about Visual C++ specifically. – user541686 Feb 07 '13 at 11:30
  • @Mehrdad, add compiler reference to the title, as a tag is easy to miss, as must admit, I did..;) – KBart Feb 07 '13 at 11:34
  • @KBart: Eh, I've also seen others complaining about redundancy... I don't know what song to dance to but in this case I think I'll leave it as-is. – user541686 Feb 07 '13 at 11:35

1 Answers1

4

It is impossible to do it with standard C++, but it is possible to use a compiler specific pragma or attribute for your structure.

in VC++, it is #pragma pack

Also to get size of 2 only, you have to do this:

#pragma pack(1)
struct s{
  unsigned short s1: 15;
  unsigned short b1: 1;
};

With #pragma pack on your code as follows:

struct S
{
    unsigned short x : 15;
    bool a : 1;
};

A hypothetical memory layout would be:

----------------------
+ 1 | 2 | 3 | 4 | 5 | ..
+   x   | a |
+---------------------

Hence it occupies 3 bytes

changing bool a to unsigned short a you get this:

-------------------------
+ 1 | 2 | 3 | 4 | 5| ..
+   x |a|
-------------------------

Which occupies only 2 bytes.

The compiler decides that, since the second short is only taking 1 bit, it is possible to just squeeze the structure into 2 bytes. But if a structure member of another type is used (such as bool in your implementation of S) the compiler thinks, since the types are different, it cannot actually squeeze the 1 bit into unsigned short(because it is crossing the type boundary - unfortunately implementation defined). Hence you get 3 bytes for sizeof() instead of 2.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • +1 because it works, but *not* because of the pragma you mentioned! It seems to be because of the type... but why does changing `bool` to `unsigned short` make a difference? – user541686 Feb 07 '13 at 11:24
  • One reason only, bool will take an extra byte for 1 bit. with unsigned short, it will try to pack everything in a short. – Aniket Inge Feb 07 '13 at 11:25
  • @Aniket Actually, there's no reason other than that's what the implementers of the compiler decided to do. It's all very arbitrary and implementation defined. – James Kanze Feb 07 '13 at 11:27
  • @Aniket: You're just repeating what's obviously happening, but I'm asking **why** does it do that? – user541686 Feb 07 '13 at 11:27
  • 1
    @JamesKanze as I said, its implementation defined. Its not standard C++ and C++ standard does not allow non-padded structures AFAIR – Aniket Inge Feb 07 '13 at 11:27
  • @JamesKanze: So are you saying Visual C++ made the arbitrary decision, "if the type changes, then pad"? – user541686 Feb 07 '13 at 11:29
  • @Aniket: Thanks for the edit, but you keep on saying *"the compiler thinks..."*, which begs what I was asking: ***why*** does it think that? Is it an arbitrary decision, is it random behavior, or is there a reason behind it? The fact that it's "thinking" something and making a decision is obvious enough now that we know what's happening, but the explanation for **why** is what I'm not understanding. – user541686 Feb 07 '13 at 11:37
  • @Mehrdad More or less. Practically speaking, _all_ decisions as to how to layout bit fields are more or less arbitrary. – James Kanze Feb 07 '13 at 12:00
  • @Aniket Since when can't you assign a `bool` to an `unsigned short`. Both are integral types, and convert freely. – James Kanze Feb 07 '13 at 12:01