2012-04-22 29 views
2

Cビットフィールドは、(おそらく精度ビット)

こんにちはビットフィールドを理解するために、いくつかの経験をして、このコードを持っている:data = 12343;を使用して

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 } 

をし、期待通りmemLoc = 01;またはmemLoc = 10;でのprintfは、すべてが表示されます。

data = 12346;memLoc = 01;またはmemLoc = 10;と同じことを使用してください。 printfはすべて期待どおりに表示されます。

しかし、私は両方のケースで何が期待されているかが表示されますmemLoc = 01;プリントを使用する場合、私はdata = 12344;またはdata = 12345;を使用しますが、私は最初のケースでmemLoc = 10;を使用する場合、それはData stored: 12346を印刷する第2のケースData stored: 12347になります。

どうしてですか?

+4

あなたは「memLoc」の2ビットのみを留保します。したがって、0〜3の値しか格納できません。しかし、あなたは10を入れます。 –

+3

ビットフィールドに 'unsigned int'も使用してください。なぜなら、左のビットシフトは、左のオペランドが負の場合には未定義であるからです(関連[question](http://stackoverflow.com/q/3784996/1250595))。また、先行する数字は0で終わらないようにします。これはCが数字を8進数として解釈するためです。例えば010 = 8. – Anthales

+0

@HansPassantありがとう。バイナリで考えていた。 2 – Favolas

答えて

2

あなたは、読み取り/書き込みビットフィールドのために、このC structを使用することができます。

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

あなたのコードの意志は次のようになります。

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); 

    // ... 
} 

が各分野でどのように多くのビットを教えてください、と私あなたのためにその構造を修正します。ここで

は、ビットフィールドについての記事です:http://en.wikipedia.org/wiki/Bit_field

+1

'int numberInt = *(int *)&number;'( 'int&'は 'int'でなければなりません)という行は良い習慣ではありません。 '2 * sizeof(short)'ビット、 'short'は16ビット、'&number'は正しく整列されます。ちょっと良い(意図しない言い回し)と書いてみると、 'uint32_t numberInt; memcpy(&numberInt、&number) 'を使い、' short'の代わりに 'uint16_t'を使います。 'data'メンバの前に構造体にパディングができないかどうかはわかりません。 – Anthales

+0

同意します。ただ修正しました。 – k06a

+0

これはまだポインタの整列問題( 'memcpy'がうまくいきます)がありますが、OPはビットフィールドを理解しようとしているだけで、移植性の高いビットフィールドライブラリ(MPBFL ™)。 – Anthales

関連する問題