Page 1 of 1

The problem with bit-fields

Posted: Tue Feb 26, 2008 9:30 pm
by Zenith
I've been working on my OS for quite a while now. Looking at some other people's code, I saw some C code that I didn't recognize: bit-fields! :shock:

So I figured out what they were, etc... but they really bug me and I'm unsure if using them is a good idea.

Pros:
- Makes things easier (more organized)
- Lets the compiler do the bit accessing for you

Cons:
- Bit-fields HAVE to be part of an unsigned/signed int :(
- Endianness is implementation specific (but for an x86 OS (little-endian), it wouldn't matter since anyone who compiles it on a big-endian architecture would be using a cross compiler, right?)

Any ideas? Who uses bit-fields and who uses bit-masks, and why?

Posted: Fri Feb 29, 2008 2:35 am
by JamesM
Cons:
- Bit-fields HAVE to be part of an unsigned/signed int Sad
Why is this a problem?
- Endianness is implementation specific (but for an x86 OS (little-endian), it wouldn't matter since anyone who compiles it on a big-endian architecture would be using a cross compiler, right?)
Endianness is specific to the target architecture (the arch the compiler is compiler *for*, not *on*). If you recompile for a target architecture with a different endianness you're pretty much always going to run into problems. Anyway IIRC bitfields don't have any endianness problems.

Posted: Wed Mar 05, 2008 4:53 am
by bewing
And it makes it less likely for someone who understands bitfields to make a coding error.
And it makes it more likely that someone unfamiliar with bitfields will totally screw up your code -- because the bitfield syntax is ugly as hell.
And your code would not compile on an old K&R C compiler -- since bitfields are a dangling ANSI add-on.

Re: The problem with bit-fields

Posted: Thu Mar 13, 2008 5:07 am
by mrvn
karekare0 wrote: Cons:
- Bit-fields HAVE to be part of an unsigned/signed int :(
- Endianness is implementation specific (but for an x86 OS (little-endian), it wouldn't matter since anyone who compiles it on a big-endian architecture would be using a cross compiler, right?)

Any ideas? Who uses bit-fields and who uses bit-masks, and why?
Bit-fields don't have to be part of an unsigned/signed int. They only need to be part of an integer type. And the type used matters in how the compiler can store bits. Lets say you want to use a bitfield for 16bit graphics output. So you have 5 bits per color channel. That fits into uin8_t just fine. So lets define out color like this:

Code: Select all

struct Color {
  uint8_t r:5;
  uint8_t g:5;
  uint8_t b:5;
};
But surprise, surprise. That structure will use 3 bytes and not 2 like we wanted. The problem here is that bit fields can only be combined up to the size of the integer type used. You can't fit 2 5-bit integers into 8 bit. The right structure would have been:

Code: Select all

struct Color {
  uint16_t r:5;
  uint16_t g:5;
  uint16_t b:5;
};
This gives a nice 2 bytes size and hopefully the right offsets for each color. How to define your bitfileds so they exactly match the bit layout you need will be compiler and architecture specific. Like many other things in your OS. So, as long as you are aware of this, it hardly makes things worse.


I tried using bitfields in my own code and kind of decided against it though. While their use is verry nice the code they generate is not. I defined a bitfield describing the Page Table Entry for amd64 and then created some page table entries to map pages. The whole structure is 64bit so this should result in a simple instruction loading a 64bit value, or so I hoped. Instead the compiler would generate code to set individual bits in the field, sometimes combining a few bits, sometimes not.

As a solution I used an union of uint64_t and the bitfield. That way I can access the full page table entry in one go, extract a set of flags by masking bits etc on the one hand and on the other hand I can use the bitfield to access indivdual flags with a nice syntax:

MfG
Goswin

Re: The problem with bit-fields

Posted: Thu Mar 13, 2008 7:25 am
by Zenith
I decided that I'll only use bitfields where it would be easier to use them compared to bitmasks - most likely for page directories/tables, possibly segment descriptors, and idt stuff, but that's it.

I still find bitmasks easier to work with...
mrvn wrote: Bit-fields don't have to be part of an unsigned/signed int. They only need to be part of an integer type. And the type used matters in how the compiler can store bits.
Yes, but unsigned/signed int is the only standard-conforming one. Using other integer types are compiler extensions and might not supported on all compilers/architectures.

Re: The problem with bit-fields

Posted: Thu Mar 13, 2008 7:26 am
by Solar
mrvn wrote:As a solution I used an union of uint64_t and the bitfield. That way I can access the full page table entry in one go, extract a set of flags by masking bits etc on the one hand and on the other hand I can use the bitfield to access indivdual flags with a nice syntax.
Hear ye! Hear ye!

:!: Excellent design decision! :!:

Posted: Thu Mar 13, 2008 2:03 pm
by os.hacker64
speaking of bitfields, how does gcc order them, what is the most significant bit in the struct, how do I control this.

Posted: Sat Mar 15, 2008 2:29 am
by pcmattman
os.hacker64 wrote:speaking of bitfields, how does gcc order them, what is the most significant bit in the struct, how do I control this.
By the order of the defined variables in the struct...