【问题标题】:C pasting tokens in MACROS for processing bit fields in CC 在 MACROS 中粘贴标记以处理 C 中的位字段
【发布时间】:2013-10-04 08:55:13
【问题描述】:

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

【问题讨论】:

    标签: c macros token


    【解决方案1】:

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

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

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

    ## 连接实际上将文本 i 附加到文本 b.bit,从而生成表达式 b.biti,从而产生您提到的错误。

    AFAIK 无法访问任意位字段成员 - 一种替代方法是仅使用按位算术(毕竟,这就是编译器生成位字段访问的方式)。

    【讨论】:

      【解决方案2】:

      有没有办法解决这个问题?

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

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

      【讨论】:

      • 谢谢..但是在处理大量结构和 64 位整数时不会消耗内存吗?所以,我正在寻找上述实现。也是我想到使用位操作的另一种方式,例如 (a & (1
      • @user2218872 位操作通常是位域代码被翻译的内容;你只是在自动生成&gt;&gt;&amp;
      【解决方案3】:

      你必须改变这样做的方式。

       #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 不要使用位域来对字进行位访问,这不是正确的方法。

      【讨论】:

        【解决方案4】:

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

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

        但是,带有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);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-11-22
          • 2021-11-13
          • 1970-01-01
          • 2021-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-15
          相关资源
          最近更新 更多