1

I was recently playing around with bit fields in C, and apparently, the bits are ordered from low to high, although Google does not support this thesis (e.g. Wikipedia.)

Take the following code (http://ideone.com/UwWfJM):

#include <stdio.h>

struct bits {
    unsigned char a : 1;
    unsigned char b : 1;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
    unsigned char f : 1;
    unsigned char g : 1;
    unsigned char h : 1;
};

int main(int argc, char **argv)
{
    unsigned char c = 33;
    struct bits *b = (struct bits *) &c;

    printf("dec: %u\n", c);
    printf("bits: %x", b->a);
    printf("%x", b->b);
    printf("%x", b->c);
    printf("%x", b->d);
    printf("%x", b->e);
    printf("%x", b->f);
    printf("%x", b->g);
    printf("%x\n", b->h);

    return 0;
}

The output is

dec: 33
bits: 10000100

...although I had expected the bit ordering to be the other way around (i.e. 00100001, with the MSB in the first place and the LSB in the last place).

Can somebody explain this behaviour?
Furthermore, can I assume that the mapping will always be in this direction?

Note: I am not asking about endianness, which is about the byte order. The background of my question is that I tried to map a buffer to a struct. The buffer contained a UDP message, consisting of a "bit mapping" (i.e. "bit at position x means this, bits at position y to z mean that, and so on).

Thanks!

  • `00100001, with the MSB in the first place and the LSB in the last place` i can't understand this sentence since your `first` and `last` is very ambiguous. could you explain your expectation more in details? btw, pay attention to you printing order, you print `a` first, which yields the first `1`. maybe you misunderstood. – Jason Hu Sep 09 '15 at 16:40
  • btw, since your example is using `char` and 8 bit long bit field composition, it indeed has nothing to do with endian. in the struct, `a` represents the lowest bit, which is correct. again, probably you are having a misunderstanding to the printing. – Jason Hu Sep 09 '15 at 16:42
  • Well, with `first` and `last` I was referring to the bits shown in the output in a left-to-right reading order. I am well aware that e.g. `b->a` is printed first and outputs `1`. This was the very core of my question (and has already been anwered by @andrew-henle ). – lima.sierra Sep 09 '15 at 16:51

3 Answers3

6

Per 6.7.2.1 of the C standard:

The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • Thanks, perfect answer! – lima.sierra Sep 09 '15 at 16:52
  • While the order of bit-fields is not defined by the C standard, it is not random. The compiler will assign bits in a well-defined manner *for that compiler and architecture*. However, for best cross-platform compatibility it might be best to avoid bit fields altogether and use "shift and mask" macros instead. – TeasingDart Sep 09 '15 at 17:04
1

I believe your confusion is in the way you presented the result. You expected it to be printed with the LSB on the right like a normal number, but your code prints a string of bits starting with the LSB on the left and printing to the right.

Your result shows bit a in the lowest (first, least significant) memory bit as expected.

TeasingDart
  • 371
  • 1
  • 6
0

The memory layout of bit fields is not defined so its compiler dependent. You can go throughenter link description here

Community
  • 1
  • 1
LearningC
  • 3,182
  • 1
  • 12
  • 19