2012-04-22 26 views
2

做了一些經驗,瞭解位域C位字段(可能是位精度)

喜有此代碼:

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 } 

使用data = 12343;memLoc = 01;memLoc = 10;中的printf將顯示所有預期。

使用data = 12346;memLoc = 01;memLoc = 10;它是同樣的事情。 printf將按預期顯示。

但是,如果使用data = 12344;data = 12345;如果我使用memLoc = 01;打印將展示什麼是在這兩種情況下預期,但如果我在第一種情況下使用memLoc = 10;將打印Data stored: 12346和第二種情況Data stored: 12347

這是怎麼發生的?

+4

你只保留2位爲「memLoc」。所以它只能存儲0到3的值。但是你可以填入10。 – 2012-04-22 17:28:22

+3

對於位字段,還使用'unsigned int',因爲左操作數爲負時左邊的位移不確定(相關[問題](http://stackoverflow.com/q/3784996/1250595))。還要避免前面的數字爲0,因爲C會將該數字解釋爲八進制數;例如010 = 8. – Anthales 2012-04-22 17:38:37

+0

@HansPassant謝謝。正在考慮二進制。應該是2 – Favolas 2012-04-22 18:22:28

回答

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 intInt = *(int *)&number;'('int&'應該是'int')這行不是好習慣,因爲假設'int' '2 * sizeof(short)'位,'short'爲16位,'&number'爲正確對齊。更好一點(沒有雙關語意圖)將寫:'uint32_t numberInt; memcpy(&numberInt,&number)'並使用'uint16_t'而不是'short';儘管我不確定在'data'成員之前是否有結構中沒有填充。 – Anthales 2012-04-22 18:25:13

+0

同意。剛剛修好。 – k06a 2012-04-22 18:51:22

+0

它仍然存在指針對齊問題('memcpy'工作),但另一方面,這可能無關緊要,因爲OP只是試圖理解位域,而不是試圖編寫最便攜的位域庫(MPBFL ™)。 – Anthales 2012-04-22 18:56:51