Bitmask vs bitfields

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • lithiumcat@gmail.com

    Bitmask vs bitfields

    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.
  • Ian Collins

    #2
    Re: Bitmask vs bitfields

    lithiumcat@gmai l.com wrote:
    /* 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, structures are copied byte for byte.
    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.
    >
    Strictly, no. But in practice I have never had a problem using them.
    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.
    >
    That you will have to measure on your platform.
    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?
    >
    It's down to you and your requirements. I prefer bitfields for the
    reasons you mention.

    --
    Ian Collins.

    Comment

    • Ben Bacarisse

      #3
      Re: Bitmask vs bitfields

      lithiumcat@gmai l.com writes:
      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.
      Yes, it is fine, but you need have named your struct or you won't be
      able to declare the other_flags variable.
      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.
      Yes. Portability is affected by things like the largest bitfield that
      is allowed, and the mapping onto values actual bit positions. You
      case is OK.
      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.
      Do you care about such fine differences? If you do, the only recourse
      is to measure and see.
      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?
      The main disadvantage (that I can see) is that bits can't be tested
      in sets. If you are happy to abandon that usage, then you must also
      ask why you don't just have a struct with char fields. This has a few
      (slight) advantages over using bit fields and it is unlikely that
      the wasted space matters except where the program needs lots of copies
      of the struct.

      --
      Ben.

      Comment

      • Ian Collins

        #4
        Re: Bitmask vs bitfields

        Ben Bacarisse wrote:
        >
        The main disadvantage (that I can see) is that bits can't be tested
        in sets. If you are happy to abandon that usage, then you must also
        ask why you don't just have a struct with char fields. This has a few
        (slight) advantages over using bit fields and it is unlikely that
        the wasted space matters except where the program needs lots of copies
        of the struct.
        >
        Or the bits map to hardware.

        --
        Ian Collins.

        Comment

        • Ian Collins

          #5
          Re: Bitmask vs bitfields

          Ian Collins wrote:
          Ben Bacarisse wrote:
          >The main disadvantage (that I can see) is that bits can't be tested
          >in sets. If you are happy to abandon that usage, then you must also
          >ask why you don't just have a struct with char fields. This has a few
          >(slight) advantages over using bit fields and it is unlikely that
          >the wasted space matters except where the program needs lots of copies
          >of the struct.
          >>
          Or the bits map to hardware.
          >
          Or bits in some other externally defined object.

          --
          Ian Collins.

          Comment

          • lithiumcat@gmail.com

            #6
            Re: Bitmask vs bitfields

            On Apr 17, 10:55 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
            lithium...@gmai l.com 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.
            >
            Do you care about such fine differences? If you do, the only recourse
            is to measure and see.
            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.
            Could you please help me choosing between the two methods?
            >
            The main disadvantage (that I can see) is that bits can't be tested
            in sets. If you are happy to abandon that usage, then you must also
            ask why you don't just have a struct with char fields. This has a few
            (slight) advantages over using bit fields and it is unlikely that
            the wasted space matters except where the program needs lots of copies
            of the struct.
            I've seldom needed to test a set of flags, and when it was the case it
            was never more than two or three flags, so I don't mind abandonning
            that.

            I haven't thought about a struct of char fields, because I still can't
            see the advantages over a bitfield, except the small speed gain of not
            having to perform bit shifts under the scenes. Actually that might be
            more efficient than the bitmask method too, I should keep that in mind
            next time I have a speed-critical program. But is there any other
            advantage?

            Comment

            • Ben Bacarisse

              #7
              Re: Bitmask vs bitfields

              Ian Collins <ian-news@hotmail.co mwrites:
              Ian Collins wrote:
              >Ben Bacarisse wrote:
              >>The main disadvantage (that I can see) is that bits can't be tested
              >>in sets. If you are happy to abandon that usage, then you must also
              >>ask why you don't just have a struct with char fields. This has a few
              >>(slight) advantages over using bit fields and it is unlikely that
              >>the wasted space matters except where the program needs lots of copies
              >>of the struct.
              >>>
              >Or the bits map to hardware.
              >>
              Or bits in some other externally defined object.
              Yes, may pedant hat must have fallen off. I meant "if you are happy
              to abandon the idea of bits".

              --
              Ben.

              Comment

              • Ben Bacarisse

                #8
                Re: Bitmask vs bitfields

                lithiumcat@gmai l.com writes:
                On Apr 17, 10:55 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
                >lithium...@gma il.com writes:
                <snip>
                >The main disadvantage (that I can see) is that bits can't be tested
                >in sets. If you are happy to abandon that usage, then you must also
                >ask why you don't just have a struct with char fields. This has a few
                >(slight) advantages over using bit fields and it is unlikely that
                >the wasted space matters except where the program needs lots of copies
                >of the struct.
                >
                I've seldom needed to test a set of flags, and when it was the case it
                was never more than two or three flags, so I don't mind abandonning
                that.
                >
                I haven't thought about a struct of char fields, because I still can't
                see the advantages over a bitfield, except the small speed gain of not
                having to perform bit shifts under the scenes. Actually that might be
                more efficient than the bitmask method too, I should keep that in mind
                next time I have a speed-critical program. But is there any other
                advantage?
                In "the old days" some compilers did support bit fields, but I can't
                image there are any like that left. There will be a few situations
                where writing and then reading back a struct full of chars will be
                portable where a struct of bitfields is not (not many, but a few).

                --
                Ben.

                Comment

                • Eric Sosman

                  #9
                  Re: Bitmask vs bitfields

                  Ian Collins wrote:
                  lithiumcat@gmai l.com wrote:
                  >
                  >/* 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, structures are copied byte for byte.
                  Nitpick: What happens to padding bytes (or, in the case
                  of bit-fields, padding bits) is unspecified.
                  >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.
                  >>
                  Strictly, no. But in practice I have never had a problem using them.
                  Why "no?" Bit-fields are part of the language, the width
                  specified (1 bit) is supported on all implementations , and even
                  the implementation' s discretion to make plain-int bit-fields
                  either signed or unsigned has been explicitly overridden with
                  the `unsigned' keyword. What's non-portable?

                  --
                  Eric Sosman
                  esosman@ieee-dot-org.invalid

                  Comment

                  • Andrey Tarasevich

                    #10
                    Re: Bitmask vs bitfields

                    lithiumcat@gmai l.com wrote:
                    ...
                    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.
                    Yes, it is correct.
                    Are these codes portable?
                    Yes. As long as you are only interested in the above functionality of
                    setting/resetting/testing flags. But once it becomes important to also guarantee
                    some pre-determined allocation layout if these flags in memory, the portability
                    ends.
                    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.
                    Well, as you said it yourself, it depends on the compiler. Sometimes even good
                    optimizing compilers miss rather "obvious" optimization opportunities.
                    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.
                    It is easier to get carried away with bit fields, lose track of how much memory
                    you are actually trying to occupy and inadvertently cause data memory bloat.

                    --
                    Best regards,
                    Andrey Tarasevich

                    Comment

                    • Andrey Tarasevich

                      #11
                      Re: Bitmask vs bitfields

                      Ben Bacarisse wrote:
                      ...
                      The main disadvantage (that I can see) is that bits can't be tested
                      in sets. If you are happy to abandon that usage,
                      ...
                      Well, bitfields _can_ be tested in sets. Except that in case of bitfield the set
                      has to be described by a expression in the program source code, as in

                      if (flags.flag1 && flags.flag2 && !flags.flag3)

                      and that is indeed a problem. With "manually" implemented bitfields this test
                      can be described by a pair of run-time values (a test mask and an expected
                      value), while with language-supported bitfields this is impossible to achieve.
                      In general, this is an important difference, I'd say.

                      --
                      Best regards,
                      Andrey Tarasevich

                      Comment

                      Working...