2

I don't know why but the bit fields assignment is not working as expected. Probably is just an stupid thing, but I've not been able to locate the problem.

Any help is more than welcome.

typedef struct  a {
    unsigned char a1 :1;
    unsigned char a2 :3;
    unsigned char a3 :2;
    unsigned char a4 :2;
} __attribute__((packed)) mystruct;

int main() {
    mystruct d;
    d.a1 = 0;
    d.a2 = 2;
    d.a3 = 1;
    d.a4 = 2;

    unsigned char *val = (unsigned char*) &d;

    printf("%02X \n", *val);
    printf("%02X \n", sizeof(hola));

    exit(0);
}

returned output:

94
01

expected output:

26
01
5
  • 2
    expected results from bit fields are frequently not what you expect. rather than check all your code, I'll ask, have you taken into account all the endianness of your platform? Commented Apr 12, 2012 at 16:49
  • 2
    0x94 is correct. why do you expect 0x26? Commented Apr 12, 2012 at 16:50
  • @James if the order in was MSB first followed by LSB it would be 0x26 Commented Apr 12, 2012 at 16:52
  • I suggest you use the binary arithmetic operators if bit placement is a concern. It is more portable and as you can see, using a structure to convert bit fields is implementation defined (not consistent). Commented Apr 12, 2012 at 19:28
  • What is hola that sizeof(hola) prints 1? In C99, the format used to print size_t should be %02zX; in C89, there isn't a reliable way to handle it (which is why the z modifier was added in C99), but you could cast the result of sizeof(hola) to int since %02X expects to print an int. On a big-endian 64-bit machine, you might well get zero printed as the size. Commented Jun 16, 2013 at 6:04

2 Answers 2

8

Nearly everything about bit-fields is implementation defined. And particularly the order of bits in a unit.

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

On your implementation, the bits are stored in a unit lsb (least significant bit) first and not msb (most significant bit) first as you would expect.

What you have is:

[a1.0] [a2.0] [a2.1] [a2.2] [a2.0] [a3.1] [a4.0] [a4.1] 
   0      0      1      0      1      0      0      1
 bit 0                     -                      bit 7

 lsb                       -                      msb

which is 0x94 if you consider the left most bit is the least significant bit.

Sign up to request clarification or add additional context in comments.

5 Comments

I like my comment better than your answer - even if yours is correct :)
@KevinDTimm if you think your comment is better, make it an answer
the reason I say so is because I wanted him to figure it out himself - but I like your answer too because the answer is typically not apparent to people using bit fields and you moved him through the process nicely - kudos & upvote (also, my comment wasn't 'big' enough to be answer - not enough info)
Thanks a lot... I was thinking on LE and BigE. I've been working with such structures for a long time and it is the first time this happens. Why is it 0x94 instead of 0x64? 0110 0100 is 0x64
@jlanza fixed, lsb to msb is 0 010 10 01 and not 0 010 01 10.
8

ASCII art:

  MSB                                LSB
+----+----+----+----+----+----+----+----+
|a4.1|a4.0|a3.1|a3.0|a2.2|a2.1|a2.0| a1 |
+----+----+----+----+----+----+----+----+
| 1  | 0  | 0  | 1  | 0  | 1  | 0  | 0  |
+----+----+----+----+----+----+----+----+
|        0x9        |        0x4        |
+----+----+----+----+----+----+----+----+

As noted, the behaviour is implementation defined; this is one of two legitimate ways of organizing the data, and seems to be the format chosen on your machine. The alternative behaviour is.

  MSB                                LSB
+----+----+----+----+----+----+----+----+
| a1 |a2.2|a2.1|a2.0|a3.1|a3.0|a4.1|a4.0|
+----+----+----+----+----+----+----+----+
| 0  | 0  | 1  | 0  | 0  | 1  | 1  | 0  |
+----+----+----+----+----+----+----+----+
|        0x2        |        0x6        |
+----+----+----+----+----+----+----+----+

This was apparently the behaviour you expected.

Since it is implementation defined, you can look in the manual and find what your compiler does because the compiler must document its behaviour.

If you have portability to worry about, you will need to think about how you will organize your structure definitions to work the way you need it to work on each platform you use.

1 Comment

note that for this particular point gcc for example is referring to the ABI: "order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1): Determined by ABI" gcc.gnu.org/onlinedocs/gcc/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.