tags:

views:

320

answers:

2

What does the following C++ code mean?

unsigned char a : 1; 
unsigned char b : 7;

I guess it creates two char a and b, and both of them should be one byte long, but I have no idea what the ": 1" and ": 7" part does.

+23  A: 

The 1 and the 7 are bit sizes to limit the range of the values. They're typically found in structures and unions:

struct x {
    unsigned char a:1;
    unsigned char b:7;
} y;

creates an 8-bit value, one bit for a and 7 bits for b.

Typically used in C to access "compressed" values such as a 4-bit nybble which might be contained in the top half of an 8-bit char.

Update: For the language lawyers among us, the 9.6 section of the standard (C++0x, draft n2914) explains this in detail.

9.6 Bit-fields [class.bit]

  1. A member-declarator of the form
         identifieropt attribute-specifieropt : constant-expression
    specifies a bit-field; its length is set off from the bit-field name by a colon. The optional attribute-specifier appertains to the entity being declared. The bit-field attribute is not part of the type of the class member. The constant-expression shall be an integral constant expression with a value greater than or equal to zero. The value of the integral constant expression may be larger than the number of bits in the object representation (3.9) of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation (3.9) of the bit-field. Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [ Note: bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. — end note ]

  2. A declaration for a bit-field that omits the identifier declares an unnamed bit-field. Unnamed bit-fields are not members and cannot be initialized. [ Note: an unnamed bit-field is useful for padding to conform to externally-imposed layouts. — end note ] As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary. Only when declaring an unnamed bit-field may the value of the constant-expression be equal to zero.

  3. A bit-field shall not be a static member. A bit-field shall have integral or enumeration type (3.9.1). It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int or long bit-field is signed or unsigned. A bool value can successfully be stored in a bit-field of any nonzero size. The address-of operator & shall not be applied to a bit-field, so there are no pointers to bit-fields. A non-const reference shall not be bound to a bit-field (8.5.3). [ Note: if the initializer for a reference of type const T& is an lvalue that refers to a bit-field, the reference is bound to a temporary initialized to hold the value of the bit-field; the reference is not bound to the bit-field directly. See 8.5.3. — end note ]

  4. If the value true or false is stored into a bit-field of type bool of any size (including a one bit bit-field), the original bool value and the value of the bit-field shall compare equal. If the value of an enumerator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type (7.2), the original enumerator value and the value of the bit-field shall compare equal. [ Example:
         enum BOOL { FALSE=0, TRUE=1 };
         struct A {
              BOOL b:1;
         };
         A a;
         void f() {
              a.b = TRUE;
              if (a.b == TRUE) // yields true
              { /* ... */ }
         }
    - end example ]

paxdiablo
Strictly speaking, in pure C they wouldn't be used with `unsigned char`. C only allows `int`, `signed int` and `unsigned int` in bitfield declarations. C99 adds `_Bool`. `unsigned char` is not a legal type for bitfield in C.
AndreyT
That's an implementation issue, at least in c1x: 6.7.2.1 para4 A bit-field shall have a type that is a qualified or unqualified version of \_Bool, signed int, unsigned int, or *some other implementation-defined type*.
paxdiablo
@paxdiablo: Yes, but the "some other implementation-defined type" bit is really redundant, because implementation is always allowed to extend the language in any way it sees fit, without an explicit permission in the specific section of the standard. A C implementation can compile Pascal and Fortran code within C code - nobody prohibits it from doing that. Yet, it would be strange to discus Fortran code as possibly valid C code for that reason. The same applies to that "implemenation-defined type" as well.
AndreyT
@AndreyT : yet, this kind of wording is quite common; it notes common, reasonable extensions.
MSalters
Your example does **not** create an 8-bit value. It creates a struct containing a 1-bit and a 7-bit value. It might insert padding between them (and afaik, MSVC does just that)
jalf
@jalf, that's a *typical* use and likely to be forced by something like #pragma pack. You're right that it *may* not create an 8-bit value in the absence of other information, you are wrong that it *does* not.
paxdiablo
@AndreyT, the "implementation-defined type" bit isn't quite redundant here. If it weren't for this, the compiler would be required to give a diagnostic, because of a constraint violation. The "implementation-defined type" thing grants the compiler acceptance of other types without giving a diagnostic.
Johannes Schaub - litb
@jalf: No, MSVC will not insert padding here. MSVC inserts padding (or, more precisely, switches to a new allocation unit) whenever the declared type changes. As long as the type remains the same, MSVC will continue to fill the last unit until it is full.
AndreyT
@litb: Good point. I missed this detail somehow. Yet, I'd still defend my original comment, where by "pure C" I meant "the abstract canonical general-case C".
AndreyT
+6  A: 

I believe those would be bitfields.

Azeem.Butt
Why the downvote?
Drew Hall
Not sure, unless it's the brevity or uncertainty but here's an upvote since (1) you're technically correct; and (2) to share the love around :-)
paxdiablo