1

我正在寻找基于作为参数传递给宏的数字来访问位字段。使用以下代码时出现错误。有没有什么办法解决这一问题?“错误:在非结构或联合的情况下请求成员 'biti'”

struct 
      {

        int bit0 :1;
        int bit1 :1;
        int bit2 :1;
        int bit3 :1;
        int bit4 :1;
        int bit5 :1;
        int bit6 :1;
        int bit7 :1;
      }a_type;

a_type b;


#define get_bit_value(x) b.bit##x

for(i=0; i<=7 ;i++)
 {
int temp;
temp = get_bit_value(i);
...
}
4

4 回答 4

2

问题是该变量i在运行时只有一个值。在解析期间(当正在评估宏时),i它只是一个标记。编译器甚至不知道它i是一个变量,更不用说一个介于 0 到 7 之间的整数了。

另一种看待它的方法是查看编译器做了什么,以及代码在预处理过程中的样子:

for(i=0; i<=7 ;i++)
{
  int temp;
  temp = b.bit##i;
  ...
}

##连接从字面上将 text 附加到itext b.bit,从而产生表达式b.biti,这会产生您提到的错误。

AFAIK 没有办法访问任意位字段成员 - 另一种方法是只使用按位算术(毕竟,这就是编译器生成位字段访问的方式)。

于 2013-10-04T09:13:23.933 回答
1

有没有什么办法解决这一问题?

我担心不,但你可以使用数组来代替,像这样吗?

int type[8] = {1,1,1,1,1,1,1,1};

#define get_bit_value(x) type[x]

for(int i=0; i<8 ;i++)
{
 int temp;
 temp = get_bit_value(i);
 ...
}
于 2013-10-04T09:02:28.817 回答
0

你必须改变做事的方式。

 #define get_bit_value(b, x)  (((b)&(1 << (x)))!=0)

 #define set_bit_value(b, x)  ((b)|=(1 << (x)))

 uint8_t v = 0;

 set_bit_value(v, 5);

这是正常的做法。您使用的位域有几个缺点:

  • 正如您所注意到的,您无法对其进行索引。
  • 大小在编译时受到限制。通过显式掩码,可以轻松扩展到任何大小。
  • 它不是便携式的!(标准未定义位的顺序)。

并且生成的代码无论如何都是相同的,因为处理器还必须进行移位和屏蔽才能访问这些位。

TL;DR 不要使用位域来对字进行位访问,这不是正确的方法。

于 2013-10-04T10:02:48.907 回答
0

您将需要一个更复杂的宏,它不能基于粘贴。它必须基于选择:

#define get_bit_value(i) ((i) < 4                              \
                          ? ((i) < 2                           \
                             ? ((i) < 1 ? b.bit0 : b.bit1)     \
                             : ((i) < 3 ? b.bit2 : b.bit3))    \
                          : ((i) < 6                           \
                             ? ((i) < 5 ? b.bit4 : b.bit5)     \
                             : ((i) < 7 ? b.bit6 : b.bit7)))

但是,带有 a 的内联函数switch可能会更好地为您服务:

inline int get_bit_value (int i) {
    switch (i) {
    case 0: return b.bit0;
    case 1: return b.bit1;
    case 2: return b.bit2;
    case 3: return b.bit3;
    case 4: return b.bit4;
    case 5: return b.bit5;
    case 6: return b.bit6;
    case 7: return b.bit7;
    default: assert(0 <= i && i < 8);
    }
}
于 2013-10-04T10:25:04.047 回答