2

Doing some experiences to understand bit fields

Hi have this code:

01 #include <stdio.h> 02 #include <stdlib.h> 03 04 void AddToBitfield(int *bitfield, int bitCount, int value); 05 int ReadFromBitfield(int *bitfield, int bitCount); 06 07 int main(){ 08 /*Device list (0 Modem,1 Keyboard,2 Mouse,3 Speakers,4 Joystick,5 Flash Drive,6 Scanner,7 Printer,8 Microphone,9 Webcam,10 Monitor)*/ 09 int device=0,memLoc=0,data=0; 10 int number = 0; 11 12 memLoc = 01; /*put 01 or 10*/ 13 device = 15; /*Device id*/ 14 data = 12343; /*Data to store - Only less or equal then 65535*/ 15 16 AddToBitfield(&number,4,device); 17 AddToBitfield(&number,16,data); 18 AddToBitfield(&number,2,memLoc); 19 20 printf("--%d---\n",number); 21 22 printf("Memory location: %d\n",ReadFromBitfield(&number,2)); 23 printf("Data stored: %d\n",ReadFromBitfield(&number,16)); 24 printf("Device: %d\n",ReadFromBitfield(&number,4)); 25 26 return 0; 27 } 28 29 void AddToBitfield(int *bitfield, int bitCount, int value){ 30 *bitfield <<= bitCount; 31 *bitfield |= value; 32 } 33 34 int ReadFromBitfield(int *bitfield, int bitCount){ 35 int value = *bitfield & ((1 << bitCount) - 1); 36 *bitfield >>= bitCount; 37 38 return value; 39 } 

Using data = 12343; and with memLoc = 01; or memLoc = 10; the printf will show all as expected.

Using data = 12346; and with memLoc = 01; or memLoc = 10; its the same thing. The printf will show all as expected.

But if I use data = 12344; or data = 12345; if I use memLoc = 01; the print will show what is expected in both cases, but if i use memLoc = 10; on the first case it will print Data stored: 12346 and on the second case Data stored: 12347.

Why is this happening?

9
  • 4
    You reserve only 2 bits for "memLoc". So it can only store values 0 through 3. Yet you stuff 10 into it. Commented Apr 22, 2012 at 17:28
  • 3
    Also use unsigned int for bit fields, since left bitshifts are undefined when the left operand is negative (relevant question). Also avoid preceding numbers with a 0, since C will then interpret the number as an octal number; e.g. 010 = 8. Commented Apr 22, 2012 at 17:38
  • @HansPassant Thanks. Was thinking in binary. Should be 2 Commented Apr 22, 2012 at 18:22
  • if you want it binary try prefix with 0b: 0b010 == 2 Commented Apr 22, 2012 at 18:35
  • @moooeeeep There is no binary prefix for number constants in C and C++; although one can use boost for this. Commented Apr 22, 2012 at 18:40

1 Answer 1

2

You can use this C struct for reading/writing bit fields:

struct MyType { uint16_t memLoc:4; uint16_t device:4; uint16_t _reserved:8; uint16_t data; }; 

Your code will looks like this:

int main() { // ... struct MyType number; uint32_t numberInt; number.memLoc = 1; number.device = 15; number.data = 12343; memcpy(&numberInt, &number, sizeof(struct MyType)); printf("--%d---\n", numberInt); printf("Memory location: %d\n", number.memLoc); printf("Data stored: %d\n", number.data); printf("Device: %d\n", number.device); // ... } 

Tell me how many bits are in each field, and i'll fix that structure for you.

Here is an article about bit fields: http://en.wikipedia.org/wiki/Bit_field

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

6 Comments

The line int numberInt = *(int*)&number; (int & should be int) isn't good practice, because is for one assumes int to be exactly 2*sizeof(short) bit, short to be 16 bit and &number to be correctly aligned. A bit better (no pun intended) would be to write: uint32_t numberInt; memcpy(&numberInt, &number) and use uint16_t instead of short; although I'm not sure if there couldn't be any padding in the struct before the data member..
It still has the pointer alignment problem (which memcpy works around), but on the other hand this probably won't matter much, as OP is only trying to understand bitfields, not trying to write the most portable bitfield library (MPBFL™).
MyType needs to be preceded with struct unless you've typedefed it. Otherwise it´s not C but C++.
I should read memcpy(&numberInt, &number, sizeof(struct MyType)) - I wanted to fix my comment, but couldn't, so I didn't bother anymore ;)
I think one still does to set the _reserved member to 0... Man, I should've written my own answer; would have saved a lot of time on commenting :)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.