Bit field structures and C++

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?ISO-8859-1?Q?Marcel_M=FCller?=

    Bit field structures and C++

    Hi,

    is the following code valid?

    #include <stdio.h>

    struct X
    { bool f1:1;
    bool f2:1;
    };

    int main(int argc, char* argv[])
    { X x;
    x.f1 = true;
    x.f2 = false;
    printf("%u %u %u\n", x.f1, x.f2, sizeof x);
    return 0;
    }

    While all my compiler seem to eat the combination of bool and bit
    fields, it is not that straight forward, because normally it must be an
    unsigned integer type. And there is no implicit conversion from that to
    bool.

    In fact, the compilers also translate the following structure without
    warning:

    struct X
    { bool f1:2;
    bool f2:2;
    };


    If the code at the top is valid I would like to prefer this over
    enumeration types with the usual power of two values.

    Unfortunately at least gcc seems not to optimize expressions like
    if (x.f2)
    in a way to avoid the logical shift.


    Marcel
  • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

    #2
    Re: Bit field structures and C++

    On 2008-10-20 19:09, Marcel Müller wrote:
    Hi,
    >
    is the following code valid?
    >
    #include <stdio.h>
    >
    struct X
    { bool f1:1;
    bool f2:1;
    };
    >
    int main(int argc, char* argv[])
    { X x;
    x.f1 = true;
    x.f2 = false;
    printf("%u %u %u\n", x.f1, x.f2, sizeof x);
    return 0;
    }
    >
    While all my compiler seem to eat the combination of bool and bit
    fields, it is not that straight forward, because normally it must be an
    unsigned integer type. And there is no implicit conversion from that to
    bool.
    C++ allows bool bitfields.
    In fact, the compilers also translate the following structure without
    warning:
    >
    struct X
    { bool f1:2;
    bool f2:2;
    };
    >
    >
    If the code at the top is valid I would like to prefer this over
    enumeration types with the usual power of two values.
    >
    Unfortunately at least gcc seems not to optimize expressions like
    if (x.f2)
    in a way to avoid the logical shift.
    I doubt that there is any way to implement a bitfield without the shift,
    and often also masking.

    --
    Erik Wikström

    Comment

    • =?UTF-8?B?TWFyY2VsIE3DvGxsZXI=?=

      #3
      Re: Bit field structures and C++

      Erik Wikström wrote:
      C++ allows bool bitfields.
      OK, thanks.

      >Unfortunatel y at least gcc seems not to optimize expressions like
      > if (x.f2)
      >in a way to avoid the logical shift.
      >
      I doubt that there is any way to implement a bitfield without the shift,
      and often also masking.
      In the above case: yes.

      If I had implemented the same semantic by an enumeration type, the
      condition above would look like
      enum Y
      { f1 = 1,
      f2 = 2,
      };
      Y y;
      if (y & Y::f2)
      or similar. This does not require a shift operation, of course. In the
      same way a compiler could optimize the condition
      if (x.f2)
      by using a mask and a comparsion to zero.
      Btw. gcc really does more complex optimizations. E.g. the initial code
      int main(int argc, char* argv[])
      { X x;
      x.f1 = true;
      x.f2 = false;
      printf("%u %u %u\n", x.f1, x.f2, sizeof x);
      return 0;
      }

      is in fact translated as
      int main(int argc, char* argv[])
      { X x;
      x.f1 = true;
      x.f2 = false;
      printf("%u %u %u\n", 1, 0, 1);
      return 0;
      }
      So gcc realized that x.f1 and x.f2 are in fact constant at the execution
      of printf. The same applies to 'if' unless I put it into a subfunction
      with an X& argument.


      Marcel

      Comment

      • James Kanze

        #4
        Re: Bit field structures and C++

        On Oct 20, 7:09 pm, Marcel Müller <news.5.ma...@s pamgourmet.org>
        wrote:
        is the following code valid?
           #include <stdio.h>
           struct X
           {
        bool f1:1;
             bool f2:1;
           };
           int main(int argc, char* argv[])
           {
        X x;
             x.f1 = true;
             x.f2 = false;
             printf("%u %u %u\n", x.f1, x.f2, sizeof x);
             return 0;
           }
        While all my compiler seem to eat the combination of bool and
        bit fields, it is not that straight forward, because normally
        it must be an unsigned integer type. And there is no implicit
        conversion from that to bool.
        No implicit conversion of what to bool? In this case, you're
        passing a type bool as a vararg. In C++, bool is an integral
        type, so integral promotions apply---the actual argument will be
        passed as an int with value of either 0 or 1. In C (and I'm
        pretty sure in C++ as well), int's and unsigned int's with the
        same values have the same representation, and this special case
        of type mismatch is legal. (Note that if you passed a negative
        value, it would be undefined behavior.)

        Of course, in this particular case, C++ offers better
        alternatives:
        std::cout << x.f1 << ' ' << x.f2 ...
        In fact, the compilers also translate the following structure
        without warning:
           struct X
           {
        bool f1:2;
             bool f2:2;
           };
        Why shouldn't it?
        If the code at the top is valid I would like to prefer this
        over enumeration types with the usual power of two values.
        But they don't do the same thing.
        Unfortunately at least gcc seems not to optimize expressions
        like
           if (x.f2)
        in a way to avoid the logical shift.
        That sounds like a problem with the optimizer. I'd ask about it
        in a g++ newsgroup, or even post it as a bug report (or an
        enhancement request).

        --
        James Kanze (GABI Software) email:james.kan ze@gmail.com
        Conseils en informatique orientée objet/
        Beratung in objektorientier ter Datenverarbeitu ng
        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

        Comment

        • blargg

          #5
          Re: Bit field structures and C++

          In article <48fcbb41$0$133 88$9b4e6d93@new sspool4.arcor-online.net>,
          =?ISO-8859-1?Q?Marcel_M=FC ller?= <news.5.maazl@s pamgourmet.orgw rote:
          Hi,
          >
          is the following code valid?
          >
          #include <stdio.h>
          >
          struct X
          { bool f1:1;
          bool f2:1;
          };
          >
          int main(int argc, char* argv[])
          { X x;
          x.f1 = true;
          x.f2 = false;
          printf("%u %u %u\n", x.f1, x.f2, sizeof x);
          [...]

          BTW, you're passing a size_t where printf() expects an unsigned int. On
          machines where size_t is a larger type, like unsigned long, this will
          yield undefined behavior. Cast the sizeof to an unsigned int, or use a
          type-safe facility like iostream.

          Comment

          • Pete Becker

            #6
            Re: Bit field structures and C++

            On 2008-10-20 18:32:29 -0400, blargg.h4g@gish puppy.com (blargg) said:
            In article <48fcbb41$0$133 88$9b4e6d93@new sspool4.arcor-online.net>,
            =?ISO-8859-1?Q?Marcel_M=FC ller?= <news.5.maazl@s pamgourmet.orgw rote:
            >
            >Hi,
            >>
            >is the following code valid?
            >>
            >#include <stdio.h>
            >>
            >struct X
            >{ bool f1:1;
            >bool f2:1;
            >};
            >>
            >int main(int argc, char* argv[])
            >{ X x;
            >x.f1 = true;
            >x.f2 = false;
            >printf("%u %u %u\n", x.f1, x.f2, sizeof x);
            [...]
            >
            BTW, you're passing a size_t where printf() expects an unsigned int. On
            machines where size_t is a larger type, like unsigned long, this will
            yield undefined behavior. Cast the sizeof to an unsigned int, or use a
            type-safe facility like iostream.
            Or use "%zu" for the format specifier, if your version of printf supports C99.

            --
            Pete
            Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
            Standard C++ Library Extensions: a Tutorial and Reference
            (www.petebecker.com/tr1book)

            Comment

            • James Kanze

              #7
              Re: Bit field structures and C++

              On Oct 21, 12:32 am, blargg....@gish puppy.com (blargg) wrote:
              In article <48fcbb41$0$133 88$9b4e6...@new sspool4.arcor-online.net>,
              =?ISO-8859-1?Q?Marcel_M=FC ller?= <news.5.ma...@s pamgourmet.orgw rote:
              Hi,
              is the following code valid?
              #include <stdio.h>
              struct X
              { bool f1:1;
              bool f2:1;
              };
              int main(int argc, char* argv[])
              { X x;
              x.f1 = true;
              x.f2 = false;
              printf("%u %u %u\n", x.f1, x.f2, sizeof x);
              [...]
              BTW, you're passing a size_t where printf() expects an
              unsigned int. On machines where size_t is a larger type, like
              unsigned long, this will yield undefined behavior.
              Formally, it has nothing to do with the size of size_t per se.
              size_t is a typedef; if it is defined to be unsigned long, you
              have undefined behavior, even if the sizes are the same.
              Cast the sizeof to an unsigned int, or use a type-safe
              facility like iostream.
              --
              James Kanze (GABI Software) email:james.kan ze@gmail.com
              Conseils en informatique orientée objet/
              Beratung in objektorientier ter Datenverarbeitu ng
              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

              Comment

              Working...