2012-04-22 78 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