Bitmask vs bitfields

Discussion in 'C Programming' started by Andrew Shepson, Jun 3, 2010.

  1. Hi,

    This question seems to come up quite often, however I haven't managed
    to find an answer relevant to my case.

    I often use binary flags, and I have alaways used a "bitmask"
    technique, that is using #defined or const int powers of two, and
    using the following primitives :
    /* declaration and initizalisation of flags */ int flags = 0;
    /* setting flag */ flags |= FLAG_1;
    /* resseting flag */ flags &= ~FLAG_2;
    /* conditional setting or resetting */ if (condition) flags |= FLAG_3;
    else flags &= ~FLAG_3;
    /* testing flags */ if ((flags & FLAG_4) || !(flags & FLAG_5)) { ... }
    /* copy of the flag set */ other_flags = flags;

    These are the only operations I ever use, they are only internal
    representations. When I store or load or exchange data, I use a human-
    readable text format, which basically boils down to setting or testing
    flags with the above primitives.

    I recently came across the "bitfield" concept, so an alernate solution
    would be:
    /* declaration and initizalisation of flags */
    struct {
    unsigned flag1 : 1;
    unsigned flag2 : 1;
    unsigned flag3 : 1;
    unsigned flag4 : 1;
    unsigned flag5 : 1;
    } flags;

    /* setting flag */ flags.flag1 = 1;
    /* resetting flag */ flags.flag2 = 0;
    /* condition setting or resetting */ flags.flag3 = (condition);
    /* testing flags */ if (flags.flag4 || !flags.flag5) { ... }
    /* copy fo the flag set */ other_flags = flags;

    My first question is, is the last line correct? structure assignment
    is a new concept for me, and I'm not familiar with it.

    Are these codes portable? I have read quite a lot of portability
    warning when using bitfields, however considering the limited set of
    operations I used (in particular, the internal representation of the
    bitfield is never taken into accoutn), I can't see any problem in it.

    Is there any efficiency difference between the two methods? Of course,
    it depends on the platform and the compiler, but there might be a rule
    of thumb. I have read that the bitfield is usually less efficient,
    however I can't see while a compiler with optimization turned on would
    produce a different code than with the bitmask method.

    With my naive point of view, I can see a few advantages to the
    bitfield method : I find the code much more readable (especially for
    testing), there is no namespace problems, and I don't have to care
    whether or not I'm using more bits than the machine word or not (I
    already had to use 34 flags on a 32-bits platform with 32-bits int and
    long, and it was quite painful) so in that sense it seems more
    portable than the bitmask method.

    Could you please help me choosing between the two methods?

    Thanks in advance.
     
    Andrew Shepson, Jun 3, 2010
    #1
    1. Advertising

  2. Andrew Shepson

    Eric Sosman Guest

    On 6/3/2010 12:59 PM, Andrew Shepson wrote:
    > Hi,
    >
    > This question seems to come up quite often, however I haven't managed
    > to find an answer relevant to my case.
    >
    > I often use binary flags, and I have alaways used a "bitmask"
    > technique, that is using #defined or const int powers of two, and
    > using the following primitives :
    > /* declaration and initizalisation of flags */ int flags = 0;
    > /* setting flag */ flags |= FLAG_1;
    > /* resseting flag */ flags&= ~FLAG_2;
    > /* conditional setting or resetting */ if (condition) flags |= FLAG_3;
    > else flags&= ~FLAG_3;
    > /* testing flags */ if ((flags& FLAG_4) || !(flags& FLAG_5)) { ... }
    > /* copy of the flag set */ other_flags = flags;
    >
    > These are the only operations I ever use, they are only internal
    > representations. When I store or load or exchange data, I use a human-
    > readable text format, which basically boils down to setting or testing
    > flags with the above primitives.
    >
    > I recently came across the "bitfield" concept, so an alernate solution
    > would be:
    > /* declaration and initizalisation of flags */
    > struct {
    > unsigned flag1 : 1;
    > unsigned flag2 : 1;
    > unsigned flag3 : 1;
    > unsigned flag4 : 1;
    > unsigned flag5 : 1;
    > } flags;
    >
    > /* setting flag */ flags.flag1 = 1;
    > /* resetting flag */ flags.flag2 = 0;
    > /* condition setting or resetting */ flags.flag3 = (condition);


    Careful! If `condition' is 6, say, the original treats it as
    true but the rewrite treats it as false. Also, if `condition' is
    something like `0.33' or `strchr(blah, 'x')', you'll get strange
    results or possibly even a compilation error. Unless you're sure
    that `condition' is an integer with the value 0 or 1, try one of

    - `flags.flag3 = !!condition;'

    - `_Bool flag3 : 1;' in the struct (C99 only)

    > /* testing flags */ if (flags.flag4 || !flags.flag5) { ... }
    > /* copy fo the flag set */ other_flags = flags;
    >
    > My first question is, is the last line correct? structure assignment
    > is a new concept for me, and I'm not familiar with it.


    Yes, structs have values and can be assigned. All the named
    elements of the receiving struct receive the same values as the
    corresponding elements of the original; unnamed padding bytes and
    padding bits receive arbitrary values.

    > Are these codes portable? I have read quite a lot of portability
    > warning when using bitfields, however considering the limited set of
    > operations I used (in particular, the internal representation of the
    > bitfield is never taken into accoutn), I can't see any problem in it.


    Your use of them is portable. The things to watch out for are
    reliance on the arrangement of elements within the struct (as with
    all structs), whether a plain-int bit-field is signed or unsigned
    (but you're specifying unsigned explicitly), and avoiding widths that
    are wider than int (which your 1-bit-wide flags aren't).

    > Is there any efficiency difference between the two methods? Of course,
    > it depends on the platform and the compiler, but there might be a rule
    > of thumb. I have read that the bitfield is usually less efficient,
    > however I can't see while a compiler with optimization turned on would
    > produce a different code than with the bitmask method.


    Mu.

    > With my naive point of view, I can see a few advantages to the
    > bitfield method : I find the code much more readable (especially for
    > testing), there is no namespace problems, and I don't have to care
    > whether or not I'm using more bits than the machine word or not (I
    > already had to use 34 flags on a 32-bits platform with 32-bits int and
    > long, and it was quite painful) so in that sense it seems more
    > portable than the bitmask method.
    >
    > Could you please help me choosing between the two methods?


    Use whichever you're comfortable with, whichever you feel makes
    the code more readable.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 3, 2010
    #2
    1. Advertising

  3. Eric Sosman writes:
    >> Is there any efficiency difference between the two methods? Of course,
    >> it depends on the platform and the compiler, but there might be a rule
    >> of thumb. I have read that the bitfield is usually less efficient,
    >> however I can't see while a compiler with optimization turned on would
    >> produce a different code than with the bitmask method.

    >
    > Mu.
    >
    >> With my naive point of view, I can see a few advantages to the bitfield
    >> method : I find the code much more readable (especially for testing),
    >> there is no namespace problems, and I don't have to care whether or not
    >> I'm using more bits than the machine word or not (I already had to use
    >> 34 flags on a 32-bits platform with 32-bits int and long, and it was
    >> quite painful) so in that sense it seems more portable than the bitmask
    >> method.
    >>
    >> Could you please help me choosing between the two methods?

    >
    > Use whichever you're comfortable with, whichever you feel makes
    > the code more readable.
    >
    > --
    > Eric Sosman
    > lid


    Eric

    Thanks

    I don't care about fine differences, when speed is really an issue
    portability is no longer a concern and I measure to get the optimal
    code
    for the concerned platform.

    However I do care about large differences. For example something like
    "generally bitfield are vastly less effeciently implemented than
    bitmask
    because so few people use them" would have been enough to make me
    reconsider the use of bitfields. I'm glad this is not the case.

    PS: Why do you use
    so many spaces and such short
    lines?
     
    Andrew Shepson, Jun 3, 2010
    #3
  4. Andrew Shepson

    Eric Sosman Guest

    On 6/3/2010 2:22 PM, Andrew Shepson wrote:
    > [...]
    > PS: Why do you use
    > so many spaces and such short
    > lines?


    Efficiency.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 3, 2010
    #4
  5. Andrew Shepson

    ImpalerCore Guest

    On Jun 3, 12:59 pm, Andrew Shepson <> wrote:
    > Hi,
    >
    > This question seems to come up quite often, however I haven't managed
    > to find an answer relevant to my case.
    >
    > I often use binary flags, and I have alaways used a "bitmask"
    > technique, that is using #defined or const int powers of two, and
    > using the following primitives :
    > /* declaration and initizalisation of flags */ int flags = 0;
    > /* setting flag */ flags |= FLAG_1;
    > /* resseting flag */ flags &= ~FLAG_2;
    > /* conditional setting or resetting */ if (condition) flags |= FLAG_3;
    > else flags &= ~FLAG_3;
    > /* testing flags */ if ((flags & FLAG_4) || !(flags & FLAG_5)) { ... }
    > /* copy of the flag set */ other_flags = flags;
    >
    > These are the only operations I ever use, they are only internal
    > representations. When I store or load or exchange data, I use a human-
    > readable text format, which basically boils down to setting or testing
    > flags with the above primitives.
    >
    > I recently came across the "bitfield" concept, so an alernate solution
    > would be:
    > /* declaration and initizalisation of flags */
    > struct {
    >     unsigned flag1 : 1;
    >     unsigned flag2 : 1;
    >     unsigned flag3 : 1;
    >     unsigned flag4 : 1;
    >     unsigned flag5 : 1;
    >
    > } flags;
    >
    > /* setting flag */ flags.flag1 = 1;
    > /* resetting flag */ flags.flag2 = 0;
    > /* condition setting or resetting */ flags.flag3 = (condition);
    > /* testing flags */ if (flags.flag4 || !flags.flag5) { ... }
    > /* copy fo the flag set */ other_flags = flags;
    >
    > My first question is, is the last line correct? structure assignment
    > is a new concept for me, and I'm not familiar with it.
    >
    > Are these codes portable? I have read quite a lot of portability
    > warning when using bitfields, however considering the limited set of
    > operations I used (in particular, the internal representation of the
    > bitfield is never taken into accoutn), I can't see any problem in it.
    >
    > Is there any efficiency difference between the two methods? Of course,
    > it depends on the platform and the compiler, but there might be a rule
    > of thumb. I have read that the bitfield is usually less efficient,
    > however I can't see while a compiler with optimization turned on would
    > produce a different code than with the bitmask method.
    >
    > With my naive point of view, I can see a few advantages to the
    > bitfield method : I find the code much more readable (especially for
    > testing), there is no namespace problems, and I don't have to care
    > whether or not I'm using more bits than the machine word or not (I
    > already had to use 34 flags on a 32-bits platform with 32-bits int and
    > long, and it was quite painful) so in that sense it seems more
    > portable than the bitmask method.
    >
    > Could you please help me choosing between the two methods?


    I tend to prefer bitmasks over bitfields myself, but if I'm working
    with a library that already uses bitfields, I have no problem going
    with the flow.

    There are a couple of minor annoyances with using bitfields. The
    first is that some compilers in the embedded domain don't support
    bitfields spanning multiple bytes, so bit operations are the only
    recourse to storing bit information in 16-bit or larger blocks. The
    other annoyance is that printing a hexadecimal or binary
    representation of the bitfield requires converting the structure to an
    integer type, or making the bitfield a union with an integer type.

    One thing that I don't like about using bitmasks is that the
    readability is pretty low. While the concept may be simple, the
    implementation is not easily readable. That's why I like to implement
    bitmask operations using macros so that the concept masks the
    intricate details of what is needed to accomplish the task.

    \code snippet
    /*!
    * \brief Define the integer type used to create a bitmask of zeros
    with
    * the least-significant bit enabled.
    *
    * One of the basic constructs used in the \c bits macro library is to
    * create a mask that is all zero except for a single bit at a given
    * index. This is often implemented using the simple expression
    * <tt>1 << index</tt>. This is used to isolate single bits to be set
    * or cleared within an integer.
    *
    * There is a caveat to consider when using this expression. The
    issue
    * is that the value of \c 1 is evaluated to be of type integer. For
    * environments where the integer type is 16-bit, this expression will
    * fail when trying to set a bit with an index >= 16 in a 32-bit long
    * integer. A similar problem arises for 32-bit environments when
    * trying to use \c 1 to set a bit at index >= 32 in a 64-bit integer.
    * If this is an issue, there will typically be a warning that says
    * that the left shift count is larger than the width of the integer
    * type. If this error is found, \c C_BITS_ONE will need to be
    defined
    * as a larger integer type.
    *
    * The method to increase the width used by the macro library is to
    * specify the type explicitly. This can be specified using a
    stdint.h
    * constant like <tt>UINT64_C(1)</tt> to enable support for 64-bit
    * integers. Keep in mind that increasing the width beyond the
    default
    * integer type for the processor may incur a performance penalty for
    * all macros.
    *
    * Ideally this should be configured using Autoconf or a Makefile, but
    * for now its location is here. The \c C_BITS_ONE define can be \c 1
    * for \c int sized masks, <tt>UINT32_C(1)</tt> to enable 32-bit
    support
    * on 16-bit integer platforms, or <tt>UINT64_C(1)</tt> to enable 64-
    bit
    * support.
    */
    #define C_BITS_ONE (UINT32_C(1))

    /*!
    * \brief Determine if the bit at \c INDEX is set in \c WORD.
    * \param WORD The word.
    * \param INDEX The bit index.
    * \return A non-zero value if the bit at \c INDEX is set, \c 0 if
    clear.
    *
    * The \c INDEX range is from [0,N-1] where N is the number of bits
    * of the \c WORD integer type.
    */
    #define C_IS_BIT_SET(WORD, INDEX) (WORD & (C_BITS_ONE << (INDEX)))

    /*!
    * \brief Determine if the bit at \c INDEX is not set in \c WORD.
    * \param WORD The word.
    * \param INDEX The bit index.
    * \return A non-zero value if the bit at \c INDEX is clear, \c 0 if
    set.
    *
    * The \c INDEX range is from [0,N-1] where N is the number of bits
    * of the \c WORD integer type.
    */
    #define C_IS_BIT_CLEAR(WORD, INDEX) ( !(WORD & (C_BITS_ONE <<
    (INDEX))) )

    /*!
    * \brief Set a single bit at \c INDEX in \c WORD.
    * \param WORD The word.
    * \param INDEX The bit index.
    *
    * The \c INDEX range is from [0,N-1] where N is the number of bits
    * of the \c WORD integer type.
    */
    #define C_SET_BIT(WORD, INDEX) (WORD |= (C_BITS_ONE << (INDEX)))

    /*!
    * \brief Clear a single bit at \c INDEX in \c WORD.
    * \param WORD The word.
    * \param INDEX The bit index.
    *
    * The \c INDEX range is from [0,N-1] where N is the number of bits
    * of the \c WORD integer type.
    */
    #define C_CLEAR_BIT(WORD, INDEX) (WORD &= ~(C_BITS_ONE << (INDEX)))
    \endcode

    For example, while setting a bit in a word is conceptually simple,
    seeing it in bit operations directly is kind of ugly (and I have worse
    macros than this). If you do go the bitmask route, making a set of
    macros to implement your bitmask primitives is imo a good idea.

    Best regards,
    John D.
     
    ImpalerCore, Jun 3, 2010
    #5
  6. Andrew Shepson

    James Harris Guest

    On 3 June, 17:59, Andrew Shepson <> wrote:
    > Hi,
    >
    > This question seems to come up quite often, however I haven't managed
    > to find an answer relevant to my case.
    >
    > I often use binary flags, and I have alaways used a "bitmask"
    > technique, that is using #defined or const int powers of two, and
    > using the following primitives :
    > /* declaration and initizalisation of flags */ int flags = 0;
    > /* setting flag */ flags |= FLAG_1;
    > /* resseting flag */ flags &= ~FLAG_2;
    > /* conditional setting or resetting */ if (condition) flags |= FLAG_3;
    > else flags &= ~FLAG_3;
    > /* testing flags */ if ((flags & FLAG_4) || !(flags & FLAG_5)) { ... }
    > /* copy of the flag set */ other_flags = flags;


    FYI, some other ops

    http://codewiki.wikispaces.com/bitfield_operations.c

    and further operations can be made wrapped in the read and write
    options.

    > These are the only operations I ever use, they are only internal
    > representations. When I store or load or exchange data, I use a human-
    > readable text format, which basically boils down to setting or testing
    > flags with the above primitives.
    >
    > I recently came across the "bitfield" concept, so an alernate solution
    > would be:
    > /* declaration and initizalisation of flags */
    > struct {
    >     unsigned flag1 : 1;
    >     unsigned flag2 : 1;
    >     unsigned flag3 : 1;
    >     unsigned flag4 : 1;
    >     unsigned flag5 : 1;
    >
    > } flags;
    >
    > /* setting flag */ flags.flag1 = 1;
    > /* resetting flag */ flags.flag2 = 0;
    > /* condition setting or resetting */ flags.flag3 = (condition);
    > /* testing flags */ if (flags.flag4 || !flags.flag5) { ... }
    > /* copy fo the flag set */ other_flags = flags;
    >
    > My first question is, is the last line correct? structure assignment
    > is a new concept for me, and I'm not familiar with it.
    >
    > Are these codes portable? I have read quite a lot of portability
    > warning when using bitfields, however considering the limited set of
    > operations I used (in particular, the internal representation of the
    > bitfield is never taken into accoutn), I can't see any problem in it.
    >
    > Is there any efficiency difference between the two methods? Of course,
    > it depends on the platform and the compiler, but there might be a rule
    > of thumb. I have read that the bitfield is usually less efficient,
    > however I can't see while a compiler with optimization turned on would
    > produce a different code than with the bitmask method.
    >
    > With my naive point of view, I can see a few advantages to the
    > bitfield method : I find the code much more readable (especially for
    > testing), there is no namespace problems, and I don't have to care
    > whether or not I'm using more bits than the machine word or not (I
    > already had to use 34 flags on a 32-bits platform with 32-bits int and
    > long, and it was quite painful) so in that sense it seems more
    > portable than the bitmask method.
    >
    > Could you please help me choosing between the two methods?


    For how you are using the fields NOW it looks like both forms would be
    portable. For the sake of possible future changes, performance
    (probably), consistency and compatibility I'd suggest using your own
    bitfield operations. They may be less readable but can always be
    wrapped in macros or functions to make them more readable.

    Better yet, wrap up ALL operations on fields of bits and add methods
    to convert them to and from an external text representation (for when
    you load or exchange data). Then

    1. you have a library for handling bit fields which you can reuse, and
    debug separately

    2. you can change the implementation - such as to try to get better
    performance on a new compiler - without affecting code which uses it

    3. your function names, if well chosen, will aid readability.

    James
     
    James Harris, Jun 3, 2010
    #6
  7. Andrew Shepson

    ImpalerCore Guest

    On Jun 3, 6:53 pm, James Harris <> wrote:
    > On 3 June, 17:59, Andrew Shepson <> wrote:


    [snip]

    > > Could you please help me choosing between the two methods?

    >
    > For how you are using the fields NOW it looks like both forms would be
    > portable. For the sake of possible future changes, performance
    > (probably), consistency and compatibility I'd suggest using your own
    > bitfield operations. They may be less readable but can always be
    > wrapped in macros or functions to make them more readable.
    >
    > Better yet, wrap up ALL operations on fields of bits and add methods
    > to convert them to and from an external text representation (for when
    > you load or exchange data). Then


    Andrew could try out my 'c_bit_vsnprintf' implementation for writing a
    text string of bits. Searching for that term should bring up a
    comp.lang.c post on Apr 1.

    [snip]
     
    ImpalerCore, Jun 4, 2010
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rod Nibbe

    Bitmask & Graphics Question

    Rod Nibbe, Oct 26, 2004, in forum: Java
    Replies:
    2
    Views:
    1,630
    Rod Nibbe
    Oct 26, 2004
  2. Andrey Brozhko
    Replies:
    1
    Views:
    1,108
    Andrey Brozhko
    Dec 10, 2004
  3. =?iso-8859-9?Q?Tongu=E7?= Yumruk

    Bitmask representation of integers

    =?iso-8859-9?Q?Tongu=E7?= Yumruk, Oct 8, 2003, in forum: Python
    Replies:
    3
    Views:
    876
    Scott David Daniels
    Oct 8, 2003
  4. Xah Lee
    Replies:
    0
    Views:
    339
    Xah Lee
    Apr 23, 2007
  5. Bitmask vs bitfields

    , Apr 17, 2008, in forum: C Programming
    Replies:
    10
    Views:
    601
Loading...

Share This Page