How to use bitfields?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • cman

    How to use bitfields?

    Who can explain to me what bitfields are and how to use them in
    practice? I would need a fairly detailed explaination, I would be a
    newbie to advanced C programming features. What are the advantages of
    using bitfields?

    cman

  • Eric Sosman

    #2
    Re: How to use bitfields?

    cman wrote:
    Who can explain to me what bitfields are and how to use them in
    practice? I would need a fairly detailed explaination, I would be a
    newbie to advanced C programming features. What are the advantages of
    using bitfields?
    A bit field is an element of a struct or union, having an
    integer type but a specified "width," or number of bits. You
    can have, for example, a three-bit signed integer or a five-bit
    unsigned integer, and so on. There are restrictions on what
    "underlying types" can be used, and on what widths are possible.
    Also, it is not possible to form a pointer to a bit field (hence,
    it is not possible to create an array of bit fields).

    Bit fields have few advantages in portable code. In non-
    portable code they are sometimes used to build a struct whose
    layout corresponds to an externally-defined format of some
    kind (e.g., the sign, exponent, and significand of a `float').

    Recommendation: Learn to recognize them in code you read,
    because you will encounter them, but avoid them in new code
    that you write.

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

    Comment

    • Radamanthe

      #3
      Re: How to use bitfields?

      cman wrote:
      Who can explain to me what bitfields are and how to use them in
      practice? I would need a fairly detailed explaination, I would be a
      newbie to advanced C programming features.
      Bitfields are not an "advanced" feature of C. In fact, there is not much
      difference with other integer types beside their bit size.
      What are the advantages of using bitfields?
      Memory usage, essentially, at the very lowest possible level. Note that
      we could always do without bitfields anyway (by using bitwise operators
      like & and |). It's just for readability that bitfields are used.

      They are often used to provide an intuitive interface to an underlying
      IO register or low-level structure. This way, you use the same semantic
      to access values as any other type. Consider, as an example, a pixel
      definition in some 16 bits ARGB format:

      #include <stdio.h>
      #include <stdint.h// C99 uint16_t

      struct ARGB1555 {
      union {
      uint16_t value;
      struct {
      unsigned int blue : 5;
      unsigned int green : 5;
      unsigned int red : 5;
      unsigned int alpha : 1;
      } comp;
      } u;
      };

      int main(void)
      {
      struct ARGB1555 pixel;
      pixel.u.comp.re d = 20;
      pixel.u.comp.gr een = 22;
      pixel.u.comp.bl ue = 7;
      pixel.u.comp.al pha = 1;
      printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
      pixel.u.comp.re d,
      pixel.u.comp.gr een,
      pixel.u.comp.bl ue,
      pixel.u.comp.al pha );

      return 0;
      }

      This is far more readable than this uggly equivalent machine dependant crap:

      int main(void)
      {
      struct ARGB1555 pixel;
      pixel.u.value = (1 << 15) | (20 << 10) | (22 << 5) | 7;
      printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
      (pixel.u.value >10) & 0x1f,
      (pixel.u.value >5) & 0x1f,
      pixel.u.value & 0x1f,
      (pixel.u.value >15) & 0x1 );

      return 0;
      }

      Of course, you may use constants for components instead of bare
      hardcoded values (so porting the code would just have to redefine them,
      like bitfields), but anyway this would still make the code harder to
      read and even a lot harder to write.

      Also, think about integer operations... even the simplest would be a
      bargain without bitfields. Just consider:

      pixel.u.comp.bl ue += 12;

      Doing this simple operation without bitfields should be done with great
      care in complex and hard to read expressions. Most programmers would
      certainly introduce a temporary variable to handle it more easily, but
      still. By using bitfields, you make the code a lot more readable while
      the compiler takes care of all the masking and shifting bargain.



      --
      R.N.

      Comment

      • Keith Thompson

        #4
        Re: How to use bitfields?

        Radamanthe <tek512@free.de leteme.frwrites :
        cman wrote:
        >Who can explain to me what bitfields are and how to use them in
        >practice? I would need a fairly detailed explaination, I would be a
        >newbie to advanced C programming features.
        >
        Bitfields are not an "advanced" feature of C. In fact, there is not
        much difference with other integer types beside their bit size.
        >
        >What are the advantages of using bitfields?
        >
        Memory usage, essentially, at the very lowest possible level. Note
        that we could always do without bitfields anyway (by using bitwise
        operators like & and |). It's just for readability that bitfields are
        used.
        >
        They are often used to provide an intuitive interface to an underlying
        IO register or low-level structure. This way, you use the same
        semantic to access values as any other type. Consider, as an example,
        a pixel definition in some 16 bits ARGB format:
        [snip]

        Yes, that kind of thing is common -- but it only works if the compiler
        lays out your bit fields in exactly the way you need it to, matching
        the externally imposed data layout. The standard says very little
        about how bit fields are laid out. On the other hand, for this kind
        of low-level code, depending on the behavior of a particular compiler
        (which likely does document how it lays out bit fields) may not be a
        problem.

        --
        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
        San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
        We must do something. This is something. Therefore, we must do this.

        Comment

        • James Dow Allen

          #5
          Re: How to use bitfields?

          On Feb 18, 11:24 pm, Radamanthe <tek...@free.de leteme.frwrote:
          ...Note that
          we could always do without bitfields anyway (by using bitwise operators
          like & and |). It's just for readability that bitfields are used.
          The compiler Sun used for the 68020 would use
          the 68020's special bit-field op-codes for bitfields,
          but not for the &/| equivalents. Any other compilers?

          James

          Comment

          • J. J. Farrell

            #6
            Re: How to use bitfields?

            On Feb 18, 8:24 am, Radamanthe <tek...@free.de leteme.frwrote:
            cman wrote:
            >
            What are the advantages of using bitfields?
            >
            Memory usage, essentially, at the very lowest possible level. Note that
            we could always do without bitfields anyway (by using bitwise operators
            like & and |). It's just for readability that bitfields are used.
            >
            They are often used to provide an intuitive interface to an underlying
            IO register or low-level structure. This way, you use the same semantic
            to access values as any other type. Consider, as an example, a pixel
            definition in some 16 bits ARGB format:
            >
            #include <stdio.h>
            #include <stdint.h// C99 uint16_t
            >
            struct ARGB1555 {
            union {
            uint16_t value;
            struct {
            unsigned int blue : 5;
            unsigned int green : 5;
            unsigned int red : 5;
            unsigned int alpha : 1;
            } comp;
            } u;
            >
            };
            >
            int main(void)
            {
            struct ARGB1555 pixel;
            pixel.u.comp.re d = 20;
            pixel.u.comp.gr een = 22;
            pixel.u.comp.bl ue = 7;
            pixel.u.comp.al pha = 1;
            printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
            pixel.u.comp.re d,
            pixel.u.comp.gr een,
            pixel.u.comp.bl ue,
            pixel.u.comp.al pha );
            >
            return 0;
            >
            }
            >
            This is far more readable than this uggly equivalent machine dependant crap:
            >
            int main(void)
            {
            struct ARGB1555 pixel;
            pixel.u.value = (1 << 15) | (20 << 10) | (22 << 5) | 7;
            printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
            (pixel.u.value >10) & 0x1f,
            (pixel.u.value >5) & 0x1f,
            pixel.u.value & 0x1f,
            (pixel.u.value >15) & 0x1 );
            >
            return 0;
            >
            }
            Why do you describe the second version as "machine dependent crap"?
            Your use of bitfields in the first example is entirely implementation
            dependent, since very little about the layout of bitfields is defined
            in C. One compiler may lay them out from the most significant bit
            down, another from the least significant up, for example. If you do
            this with bitfields, you may need to re-implement your code for each
            different compiler or target.

            The second method, however, is implementation and machine independent
            and entirely portable (in principle - I've not checked the details of
            your example). Code written in this way is portable between compilers
            for the same target, and often across different targets.

            Comment

            • Radamanthe

              #7
              Re: How to use bitfields?

              J. J. Farrell wrote:
              On Feb 18, 8:24 am, Radamanthe <tek...@free.de leteme.frwrote:
              >cman wrote:
              >>
              >>What are the advantages of using bitfields?
              >Memory usage, essentially, at the very lowest possible level. Note that
              >we could always do without bitfields anyway (by using bitwise operators
              >like & and |). It's just for readability that bitfields are used.
              >>
              >They are often used to provide an intuitive interface to an underlying
              >IO register or low-level structure. This way, you use the same semantic
              >to access values as any other type. Consider, as an example, a pixel
              >definition in some 16 bits ARGB format:
              >>
              >#include <stdio.h>
              >#include <stdint.h// C99 uint16_t
              >>
              >struct ARGB1555 {
              > union {
              > uint16_t value;
              > struct {
              > unsigned int blue : 5;
              > unsigned int green : 5;
              > unsigned int red : 5;
              > unsigned int alpha : 1;
              > } comp;
              > } u;
              >>
              >};
              >>
              >int main(void)
              >{
              > struct ARGB1555 pixel;
              > pixel.u.comp.re d = 20;
              > pixel.u.comp.gr een = 22;
              > pixel.u.comp.bl ue = 7;
              > pixel.u.comp.al pha = 1;
              > printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
              > pixel.u.comp.re d,
              > pixel.u.comp.gr een,
              > pixel.u.comp.bl ue,
              > pixel.u.comp.al pha );
              >>
              > return 0;
              >>
              >}
              >>
              >This is far more readable than this uggly equivalent machine dependant crap:
              >>
              >int main(void)
              >{
              > struct ARGB1555 pixel;
              > pixel.u.value = (1 << 15) | (20 << 10) | (22 << 5) | 7;
              > printf( "red: %d, green: %d, blue: %d, alpha: %d\n",
              > (pixel.u.value >10) & 0x1f,
              > (pixel.u.value >5) & 0x1f,
              > pixel.u.value & 0x1f,
              > (pixel.u.value >15) & 0x1 );
              >>
              > return 0;
              >>
              >}
              >
              Why do you describe the second version as "machine dependent crap"?
              Because I was too lazy to write a more clean version, with mask and
              shift constants instead of hardcoded values (so it would have the same
              degree of portability than the bitfield version, at least).

              The point was to demonstrate the readability of bitfields. I could have
              gone a lot further.
              Your use of bitfields in the first example is entirely implementation
              dependent, since very little about the layout of bitfields is defined
              in C.
              Of course it is implementation dependent ! This is all about low-level
              assumptions. But only THIS definition has to be changed, not the
              potential thousands lines of code using it everywhere else.

              There is simply no way in C or any other language (maybe fragment
              shaders, but this is not as flexible as C) to make machine independant
              code for such things, as for many others. If you want speed (and believe
              me: you WANT speed when dealing with screen devices), this is the best &
              least you can do because anyway, you know that it will have to be ported
              to be efficient enough.
              One compiler may lay them out from the most significant bit
              down, another from the least significant up, for example. If you do
              this with bitfields, you may need to re-implement your code for each
              different compiler or target.
              The bitfield definition code only. All the rest is unchanged and THAT is
              the point.
              The second method, however, is implementation and machine independent
              and entirely portable (in principle - I've not checked the details of
              your example).
              No, it isn't (like the bitfield version) when you're not alone in your C
              universe and you communicate with devices somewhere else millions of
              times per second. C is not only about dealing with databases used by C
              programs only. That would be so simple.

              I don't use C because of its portability (though this is welcome), but
              because it is the only language that allow me to do pseudo-assembly
              low-level code very tied to the hardware in such a way that I don't have
              to rewrite everything for each target. In my pov, it is the greatest
              power of C and the main reason why I stick to it (or C++ eventually).
              Code written in this way is portable between compilers
              for the same target, and often across different targets.
              Is this a debate around 99.98% versus 99.99% portability ? And what is a
              target for you ? A "C machine" ? I wish computers to be only "C
              machines", I would have far less problems, but halas, my output device
              would not be able to draw pixels anyway, and this example would
              certainly have no sense.



              --
              R.N.

              Comment

              • Keith Thompson

                #8
                Re: How to use bitfields?

                Radamanthe <tek512@free.de leteme.frwrites :
                J. J. Farrell wrote:
                [...]
                >Your use of bitfields in the first example is entirely implementation
                >dependent, since very little about the layout of bitfields is defined
                >in C.
                >
                Of course it is implementation dependent ! This is all about low-level
                assumptions. But only THIS definition has to be changed, not the
                potential thousands lines of code using it everywhere else.
                >
                There is simply no way in C or any other language (maybe fragment
                shaders, but this is not as flexible as C) to make machine independant
                code for such things, as for many others. If you want speed (and
                believe me: you WANT speed when dealing with screen devices), this is
                the best & least you can do because anyway, you know that it will have
                to be ported to be efficient enough.
                <OT>
                In fact, there are machine-independent ways to do this in *some*
                languages. In Ada, for example, you can use a representation clauses
                to specify the exact layout of a record (struct) type, or you can use
                slices of a packed Boolean array.
                </OT>

                [...]
                >Code written in this way is portable between compilers
                >for the same target, and often across different targets.
                >
                Is this a debate around 99.98% versus 99.99% portability ? And what is
                a target for you ? A "C machine" ? I wish computers to be only "C
                machines", I would have far less problems, but halas, my output device
                would not be able to draw pixels anyway, and this example would
                certainly have no sense.
                Bit field layout is likely to be affected by byte ordering, which
                definitely varies from one platform to another. I suspect there are
                other variations beyond that, such as whether bit fields can cross a
                word boundary, and just what a "word" is.

                --
                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
                We must do something. This is something. Therefore, we must do this.

                Comment

                • Radamanthe

                  #9
                  Re: How to use bitfields?

                  Keith Thompson wrote:
                  Radamanthe <tek512@free.de leteme.frwrites :
                  >J. J. Farrell wrote:
                  [...]
                  >>Your use of bitfields in the first example is entirely implementation
                  >>dependent, since very little about the layout of bitfields is defined
                  >>in C.
                  >Of course it is implementation dependent ! This is all about low-level
                  >assumptions. But only THIS definition has to be changed, not the
                  >potential thousands lines of code using it everywhere else.
                  >>
                  >There is simply no way in C or any other language (maybe fragment
                  >shaders, but this is not as flexible as C) to make machine independant
                  >code for such things, as for many others. If you want speed (and
                  >believe me: you WANT speed when dealing with screen devices), this is
                  >the best & least you can do because anyway, you know that it will have
                  >to be ported to be efficient enough.
                  >
                  <OT>
                  In fact, there are machine-independent ways to do this in *some*
                  languages. In Ada, for example, you can use a representation clauses
                  to specify the exact layout of a record (struct) type, or you can use
                  slices of a packed Boolean array.
                  </OT>
                  Nice. Is it easily merged into C code or should I rewrite everything in
                  Ada ? :)
                  >>Code written in this way is portable between compilers
                  >>for the same target, and often across different targets.
                  >Is this a debate around 99.98% versus 99.99% portability ? And what is
                  >a target for you ? A "C machine" ? I wish computers to be only "C
                  >machines", I would have far less problems, but halas, my output device
                  >would not be able to draw pixels anyway, and this example would
                  >certainly have no sense.
                  >
                  Bit field layout is likely to be affected by byte ordering, which
                  definitely varies from one platform to another. I suspect there are
                  other variations beyond that, such as whether bit fields can cross a
                  word boundary, and just what a "word" is.
                  You can use padding fields to sort it out. That's not to say the
                  compiler would not be conform if it would not permit to represent the
                  required bits layout anyway, but it would be obsolete in the context of
                  adressing a given device at a such low level, thus losing a great
                  advantage of C.



                  --
                  R.N.

                  Comment

                  • Keith Thompson

                    #10
                    Re: How to use bitfields?

                    Radamanthe <tek512@free.de leteme.frwrites :
                    Keith Thompson wrote:
                    [...]
                    ><OT>
                    >In fact, there are machine-independent ways to do this in *some*
                    >languages. In Ada, for example, you can use a representation clauses
                    >to specify the exact layout of a record (struct) type, or you can use
                    >slices of a packed Boolean array.
                    ></OT>
                    >
                    Nice. Is it easily merged into C code or should I rewrite everything
                    in Ada ? :)
                    <OT>
                    Ada provides mechanisms for interfacing to C. The syntax is very
                    different, so you can't mix them at the source level. An Ada frontend
                    is an optional part of gcc.

                    It's up to you (and entirely off-topic) whether you want to use Ada.
                    </OT>

                    [...]
                    >Bit field layout is likely to be affected by byte ordering, which
                    >definitely varies from one platform to another. I suspect there are
                    >other variations beyond that, such as whether bit fields can cross a
                    >word boundary, and just what a "word" is.
                    >
                    You can use padding fields to sort it out. That's not to say the
                    compiler would not be conform if it would not permit to represent the
                    required bits layout anyway, but it would be obsolete in the context
                    of adressing a given device at a such low level, thus losing a great
                    advantage of C.
                    What do you mean by "padding fields"?

                    --
                    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
                    We must do something. This is something. Therefore, we must do this.

                    Comment

                    Working...