Bit shifting vs Bitfields

Discussion in 'C Programming' started by richard_l, Jun 13, 2006.

  1. richard_l

    richard_l Guest

    Hello All,

    I am writing an application which receives a word which is a bitmap. I
    have created a word typedef which contains a bitfield defining each
    bit. however, I was wondering however if it would be better to write a
    macro to access each bit instead of the bitfield.

    I have read the C-FAQ on bit fields, but was wondering if there were
    any advantages/disadvantages to using bit shifting. To my mind I think
    using bitfields are more logical and easier to read and use but have a
    feeling it is slower than bit shifting.

    Can anyone enlighten me on this subject?


    richard_l, Jun 13, 2006
    1. Advertisements

  2. richard_l

    Ian Collins Guest

    Don't speculate, profile!

    I'm a bit field fan for the reasons you mention and whenever I've
    bothered to look, the compiler generated very tight code to access them.

    Just make sure you don't run into any endian issues.
    Ian Collins, Jun 13, 2006
    1. Advertisements

  3. richard_l

    Jack Klein Guest

    Maybe it would, maybe not.
    Why do you care which method is faster or slower? You shouldn't care
    at all until the following program returns TRUE:

    enum { FALSE, TRUE } BOOL;

    BOOL should_I_worry_about_speed(void)
    BOOL result = FALSE;

    if (this_part_of_my_program_is_tested_and_verified_correct()
    && my_program_is_finished_and_works_correctly()
    && my_correct_program_runs_too_slowly()
    && I_have_verified_this_code_is_a_bottleneck())
    /* then and only then */
    result = TRUE;

    return result;

    Of course, you need to implement the four functions called. Or even
    better, treat this as pseudo code and just answer the questions
    yourself. If, and only if, the answers to all four questions are
    true, then you can start thinking, and testing, whether bit fields are
    faster than bit masks, or vice-versa.
    Even if all the above answers are true, the only way to know whether
    bit fields or bit masks are faster on your particular compiler and
    processor is to build test code both ways and time it.

    I have seen processors that have machine language instructions that
    support bit-field manipulation, and C compilers that use them, with
    the result that code using bit fields executes faster than code using
    bit masks. And I have seen platforms where the opposite is true.
    Jack Klein, Jun 13, 2006
  4. richard_l

    Malcolm Guest

    Bitfields were once generally badly implemented.
    There was a kind of vicious circle. Programmers used masks because the
    bitfield code was slow, and complier writers didn't bother much to optimise
    bitfields because they were rarely used.

    I am sure whether this is still the case. Now that memory sizes are so
    large, usually it doesn't make much sense to try to squash data into a
    minimal number of bits.
    Malcolm, Jun 13, 2006
  5. When I have used bit fields it has usually been to overlay a structure
    on a register of some sort, i.e. status register, where certain bits or
    groups of bits have certain meanings. To my mind this makes the code
    much more readable. This sort of thing has nothing to do with memory
    swengineer001, Jun 14, 2006
  6. Bit-mapped registers are often defined in terms of value bits, but
    bit fields are not, leading to a potential endian confusion and

    On the other hand, status registers are not portable anyhow ;-)
    Walter Roberson, Jun 14, 2006
  7. Yeah, in order for my code to need to be portable the custom ASIC will
    need a respin. I don't see anyone spending the money on that and even
    if they do they are likely not to change the processor due to the large
    amount of existing code.
    swengineer001, Jun 14, 2006
  8. richard_l

    richard_l Guest

    Hello All,

    Many thanks for the advice given. I was aware of the endian issue
    before I posted this. My main query was if there were any benefits to
    bit shifting rather than defining bit fields. I think my conclusion is
    that unless you are porting code, defining bitfields are fine. I
    would suggest that most ANSI compilers these days (I'm using gcc)
    handle bitfields in the appropriate manner.

    Thanks for all the contributions,


    richard_l, Jun 14, 2006
  9. I agree with the "appropriate handling", but not with "bit fields
    unless porting".

    I would use bit fields only if all of the following three assumptions
    are true:

    (a) It does not matter what bits are assigned to which field. [1]
    (b) The size of the structure containing the bit fields is not
    important. [2]
    (c) The alignment of a bit field structure is not important. [3]

    In most cases they are not, so I use masks + shifts.

    (*) ISO/IEC 9899:1999(E): Structure and union specifiers
    10 [2] An implementation may allocate any addressable storage unit
    large enough to hold a bitfield.
    If enough space remains, a bit-field that immediately follows another
    bit-field in a structure shall be packed into adjacent bits of the
    same unit. [2] If insufficient space remains, whether a bit-field that
    does not fit is put into the next unit or overlaps adjacent units is
    implementation-defined. [1] The order of allocation of bit-fields
    within a unit (high-order to low-order or low-order to high-order) is
    implementation-defined. [3] The alignment of the addressable storage
    unit is unspecified.
    Roberto Waltman, Jun 14, 2006
  10. richard_l

    pete Guest

    Roberto Waltman wrote:
    But even in cases when they are, those three conditions
    don't supply a reason not to use masks and shifts,
    so I always use masks and shifts.
    pete, Jun 14, 2006
  11. richard_l

    Ian Collins Guest

    Have you ever come across a real world situation where any of these are
    an issue?
    Ian Collins, Jun 14, 2006
  12. Yes...

    20-ish years ago, I did a debugger/disassembler. The bit order
    was important because some of the bits came from outside my control.
    If I had programmed in terms of bitfields then the program would
    have relied upon implementation-dependant behaviour.

    But for my purposes, it turned out to be easier to write the code
    in a table-driven manner, with bit masks and comparison values,
    so the issue was avoided -- almost accidently, you might say.

    Later I ported the disassembler part of the code to handle a completely
    different architecture. If I had written in terms of bitfields the first
    time, I would have had to rewrite to suit the compiler on the new
    architecture; as it was, it was just a matter of populating the
    table entries and writing code to handle the new addressing modes.
    The table-driven code was again easier to handle in terms of bitmasks.

    Somewhere in there is a point or two ;-) That
    (1) if you do not control the generation and storage of all the
    data to be manipulated, then the bitfield order and sizing would
    indeed be important;
    (2) that bitmasks are often easier to write for, and the code
    generalizes and simplifies more readily
    Walter Roberson, Jun 14, 2006
  13. In embedded systems and communication protocols, all the time.

    If I need, (drawing an example from a real project,) to set one of the
    hardware registers controlling a communications device, where bit 0 is
    an enable/disable flag, and bits 1 and 2 select one of four available
    transfer rates, there is no portable way to do it using bitfields.

    Lets assume the register is 8 bits wide, and I am using a 32 bit
    processor which can access 8, 16, and 32 bit "storage units"

    This struct

    struct com_ctrl
    unsigned int e:1; /* enable and rate. using one letter */
    unsigned int r:2; /* identifiers to fit in the */
    }; /* diagrams below */

    could be mapped into any of these:

    7 6 5 4 3 2 1 0
    | | | | | | r |e|

    7 6 5 4 3 2 1 0
    |e| r | | | | | |

    15 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    | | | | | | | | | | | | | | r |e|

    15 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    |e| r | | | | | | | | | | | | | |

    31 0 9 8 7 6 ... 9 8 7 6 5 4 3 2 1 0
    +-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+---+-+
    | | | | | | | ... | | | | | | | | r |e|
    +-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+---+-+

    31 0 9 8 7 6 ... 9 8 7 6 5 4 3 2 1 0
    +-+---+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+
    |e| r | | | | ... | | | | | | | | | | |
    +-+---+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+

    Not only the bit positions may not match, it is also impossible to
    copy such a structure into the control register without risking
    modifying adjacent registers.
    Roberto Waltman, Jun 14, 2006
  14. richard_l

    Ian Collins Guest

    But is it? I've never seen this happen with an embedded compiler. Bit
    fields tend to be well documented in these..
    Ian Collins, Jun 14, 2006
  15. I am not sure I understand you question. Any particular choice is
    likely to be documented and stable for a particular compiler.
    Any code relying on that choice is still not portable.

    Use that communication device I used as an example in a different
    product, with a different processor and compiler and the code may not
    work anymore.

    The same applies to the handling of fields in communication protocols
    when messages are exchanged between separate processors.

    The structure size problem can be a show stopper, documented or not.
    Roberto Waltman, Jun 15, 2006
  16. *or*

    The compiler precisely documents how it lays out bit fields, and I
    know I'll never need to worry about portability to any other compiler
    that doesn't make the same guarantees. Yes, masks and shifts will do
    the same job, but bit fields are easier to work with.

    (A good argument can be made that masks and shifts are a better idea
    even in these circumstances.)
    Keith Thompson, Jun 15, 2006
  17. richard_l

    Chris Torek Guest

    I have written drivers for two particular chips (one AMD Ethernet
    chip and one Zilog serial port chip) that have been used on MIPS
    ("both endian" and one of them had only 32-bit load/store), SPARC,
    Intel, and other CPUs. These drivers did not use bitfields,
    despite their apparent convenience, because those bitfields were
    in fact mapped differently on those different machines.

    In general, using bitfields buys you a little convenience, which
    you later pay for in effort porting the driver to new compilers
    and machines. Sometimes this tradeoff is worth it and sometimes
    it is not.
    Chris Torek, Jun 15, 2006
  18. richard_l

    Ian Collins Guest

    That's been my situation, embedded targets where the toolchain is very
    unlikely to change.
    Ian Collins, Jun 15, 2006
  19. OK, I get it now. I agree, the toolchain used for an embedded project
    is not likely to change. My comments were in the context of code that
    may be ported to different platforms. (Or, for communication
    protocols, shared among different platforms.)
    Roberto Waltman, Jun 15, 2006
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.