Sign in to follow this  
Alex Melbourne

Bit-fields

Recommended Posts

Alex Melbourne    294
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: [b]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'.[/b]

Other experiments (wider members) produce larger values for the size of the structure. Edited by BinaryPhysics

Share this post


Link to post
Share on other sites
Hodgman    51222
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. Edited by Hodgman

Share this post


Link to post
Share on other sites
Alex Melbourne    294
[quote name='Hodgman' timestamp='1347206045' post='4978329']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][/quote]

The result is that they're both 1.

[quote name='Hodgman' timestamp='1347206045' post='4978329']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.[/quote]

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? Edited by BinaryPhysics

Share this post


Link to post
Share on other sites
Hodgman    51222
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 [i]for that one compiler[/i]. 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] Edited by Hodgman

Share this post


Link to post
Share on other sites
Alex Melbourne    294
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.

Share this post


Link to post
Share on other sites
swiftcoder    18426
[quote name='BinaryPhysics' timestamp='1347206360' post='4978331']
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?[/quote]
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.

Share this post


Link to post
Share on other sites
Alex Melbourne    294
[quote name='swiftcoder' timestamp='1347217591' post='4978366']I honestly can't see a reason *why* the compiler would allocate a smaller size...[/quote]

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

Share this post


Link to post
Share on other sites
swiftcoder    18426
[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.[/quote]
The MSDN page suggests that [url="http://msdn.microsoft.com/en-us/library/yszfawxh(v=vs.80).aspx"]allowing char-sized bitfields is a non-standard extension[/url], 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 :)

Share this post


Link to post
Share on other sites
Cornstalks    7030
[quote name='swiftcoder' timestamp='1347230020' post='4978411']
[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.[/quote]
The MSDN page suggests that [url="http://msdn.microsoft.com/en-us/library/yszfawxh(v=vs.80).aspx"]allowing char-sized bitfields is a non-standard extension[/url], 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:

[quote]
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this