Bit-fields

Started by
8 comments, last by Alex Melbourne 11 years, 8 months ago
This has been bugging me since last night. It is really for abstract, educational purpose so I'm not after a "bit-fields are evil, do not use them" response.

As stated the question I have concerns bit-fields; as in:
[source lang="cpp"]/*
** flags used to describe the state of a log file
*/
struct flags
{
unsigned open : 1;
unsigned redirected : 1;
unsigned error : 1;
unsigned : 5;
};[/source]Now, logically (based on the explanations of bit-fields) the statment: [source lang="cpp"]sizeof (struct flags) == 1[/source] Should be true.

However, (using Visual Studio 2010) the size of the structure is actually 4 'bytes'. Further reading statement that bit-fields are highly implementation dependent in C. So I put the size down to that and moved on.

But now, grammar states that the 'sizeof' operator cannot be applied to bit-fields.

So this leaves me with a question: Is the operator actually returning the right value and bit-fields aren't actually implemented as the specification states, or is it the fact that the operator is wrong and I can take it on blind faith that the structure is the right 'wide'.

Other experiments (wider members) produce larger values for the size of the structure.
Advertisement
Try sizeof with [font=courier new,courier,monospace]struct flags { char data; }; [/font]and [font=courier new,courier,monospace]struct flags { char open : 1; }[/font]
It's probably implemented by making a struct with an 'unsigned' inside it, and then you're specifying meanings for 8 of the bits that make up the unsigned.
Try sizeof with [font=courier new,courier,monospace]struct flags { char data; }; [/font]and [font=courier new,courier,monospace]struct flags { char open : 1; }[/font]


The result is that they're both 1.

It's probably implemented by making a struct with an 'unsigned' inside it, and then you're specifying meanings for 8 of the bits that make up the unsigned.


That makes sense considering the size of an unsigned is 4. Does this mean I can't necessarily take it on faith? Is the size actually implementation dependent too?
The fact that sizeof returns 4 means that the compiler assumes that when using that struct, you'll have allocated 4 bytes for it.
You could just allocate 1 byte and cast it to your struct, but for all you know, you'll read outside the bounds of your allocation by 3 bytes. You can test whether this is true or not, and if it does behave correctly, then your code is fine for that one compiler. You'll have to redo the tests whenever you change compilers.

If the char version works, why not just use that?
You could also add a static assertion, so that the code will be flagged as broken if some other compiler is incompatible, e.g. [font=courier new,courier,monospace]STATIC_ASSERT( sizeof(struct flags) == 1 );[/font]
I think probably using the version that you suggested is the simplest method. Nice a precise.

I was just curious about the 'real world' versions of text book example since I'm simply working through the grammar and elements of the language.

Thanks for your help.

That makes sense considering the size of an unsigned is 4. Does this mean I can't necessarily take it on faith? Is the size actually implementation dependent too?

I honestly can't see a reason *why* the compiler would allocate a smaller size than the size of the type you have requested. If you want a maximum size of 1, use a char as the base type for your bitfield.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I honestly can't see a reason *why* the compiler would allocate a smaller size...


The example in "The C Programming Language simply states that flags should be made up of unsigned integers.

The example in "The C Programming Language simply states that flags should be made up of unsigned integers.

The MSDN page suggests that allowing char-sized bitfields is a non-standard extension, which would support that view. I'd be interested to see the relevant reference to the standard.

Although, it also strikes me that there is very little reason to allocate a struct of less than 4 bytes - if one is encapsulating that little data, there is a design issue. Not to mention that the overhead of dynamically allocating such a struct would be ridiculous :)

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


[quote name='BinaryPhysics' timestamp='1347227760' post='4978396']
The example in "The C Programming Language simply states that flags should be made up of unsigned integers.

The MSDN page suggests that allowing char-sized bitfields is a non-standard extension, which would support that view. I'd be interested to see the relevant reference to the standard.
[/quote]
Section 6.7.2.1, paragraph 4:


A bit-?eld shall have a type that is a quali?ed or unquali?ed version of _Bool, signed int, unsigned int, or some other implementation-de?ned type.
[/quote]


The C++ standard (section 9.6, paragraph 3) is a little different in this regard, and says "A bit-?eld shall have integral or enumeration type (3.9.1). It is implementation-de?ned whether a plain (neither explicitly signed nor unsigned) char, short, int, long, or long long bit-?eld is signed or unsigned"(which implies char, short, int, long, and long long are allowed), and may be why MSVC's compiler allows for more than just _Bool, signed int, and unsigned int.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
I think if I use bit-fields I'll stick to the standard then. Might as well make them any more less specific to a given compiler.

This topic is closed to new replies.

Advertisement