【问题标题】:Bit Position of a Number at Compile Time编译时数字的位位置
【发布时间】:2014-02-27 16:53:15
【问题描述】:

我正在使用 C 在嵌入式系统上实现定点数学。

为了便于阅读,我将分母表示为 2 的幂:

#define Fixed_Point_Base 4096U

但是,当我在定点数学之间进行转换时,我需要移位量:

#define Fixed_Point_Bit_Position 12U

为了使维护更容易,代码更健壮,我想有一个#define 用于表示 Fixed_Point_Base 数的位位置(移位数):

#define Fixed_Point_Bit_Position(x) {/*...*/}

我知道的唯一方法涉及对数和除法,我真的不想在嵌入式系统中使用对数或除法:

bit count = ln(4096) / ln(2)

我正在寻找返回 2 的幂的位位置的预处理器宏或编译时解决方案。

我的网络搜索返回了代码中的示例,但不是编译时/预处理器解决方案。

仅供参考,我使用的是带有 ARM7TDMI 处理器的 IAR Embedded Workbench。
编辑 1:我使用的是 MISRA C 2004 指南以及 Parasoft 静态分析和 Coverity 静态分析工具。答案必须通过这些限制。

【问题讨论】:

  • 反过来(定义Fixed_Point_Bit_Position,使用Fixed_Point_Base(x) 得到分母)将是微不足道的。你不能这样做吗?
  • 那可读性差,Fixed_Point_Base(12) 可读性不如 4096U。

标签: c embedded c-preprocessor compile-time fixed-point


【解决方案1】:

你的问题与我的一个老问题高度相关:

Is there any way to compute the width of an integer type at compile-time?

接受的答案可以解决您的问题:

https://stackoverflow.com/a/4589384/379897

特别是,使用:

#define Fixed_Point_Bit_Position(x) IMAX_BITS((x)-1)

IMAX_BITS 是该答案中的宏之一。

【讨论】:

    【解决方案2】:

    您可以通过定义位精度并从那里确定 Fixed_Point_Base 来执行当前操作的相反操作,如下所示:

    #define PRECISIONS_IN_BITS ( 12 )
    #define FIXED_POINT_BASE   ( 1 << PRECISION_IN_BITS )
    

    这样你就可以只维护一个号码。

    【讨论】:

    • 不错的答案,但是,我的编译器和静态分析工具需要测试表达式 (1 &lt;&lt; PRECISION_IN_BITS) 以验证表达式不会溢出单词中的位数。这就是我们使用十进制数字而不是移位表达式的原因。
    • 但是字面量 1 的类型是 int,并且保证至少为 16 位,因此 编译时 保证不会溢出。我不明白为什么静态分析会抱怨 - 这是一个完全传统的习语。但是我建议((unsigned)(1u &lt;&lt; PRECISION_IN_BITS)) 并将PRECISION_IN_BITS 定义为12u
    【解决方案3】:

    蛮力适用于此!

    生成 C 级常量表达式的简单(嗯,“简单”)解决方案(可用于编译时常量,例如数组大小):

    #define Fixed_Point_Base 4096U
    
    #define FPB_BITSET(X, K) (((Fixed_Point_Base >> (X) & 1) == 1) ? (X) : (K))
    #define MAX_FP_BIT_32 FPB_BITSET(31, FPB_BITSET(30, FPB_BITSET(29, FPB_BITSET(28, FPB_BITSET(27, FPB_BITSET(26, FPB_BITSET(25, FPB_BITSET(24, \
                          FPB_BITSET(23, FPB_BITSET(22, FPB_BITSET(21, FPB_BITSET(20, FPB_BITSET(19, FPB_BITSET(18, FPB_BITSET(17, FPB_BITSET(16, \
                          FPB_BITSET(15, FPB_BITSET(14, FPB_BITSET(13, FPB_BITSET(12, FPB_BITSET(11, FPB_BITSET(10, FPB_BITSET(9, FPB_BITSET(8, \
                          FPB_BITSET(7, FPB_BITSET(6, FPB_BITSET(5, FPB_BITSET(4, FPB_BITSET(3, FPB_BITSET(2, FPB_BITSET(1, FPB_BITSET(0, -1 \
                          ))))))))))))))))))))))))))))))))
    const unsigned int Fixed_Point_Bit_Position = MAX_FP_BIT_32;
    

    为了我的粘贴手指而限制为 32 位:扩展它是微不足道的。三元运算符是一个常量表达式,这似乎是一个鲜为人知的事实。

    仅预处理器版本(如果您需要标记粘贴结果或其他内容):

    #define FPB_BITSET(X) (((Fixed_Point_Base >> (X) & 1) == 1) * (X))
    
    #if FPB_BITSET(31)
    #  define Fixed_Point_Bit_Position 31
    #elif FPB_BITSET(30)
    #  define Fixed_Point_Bit_Position 30
    #elif FPB_BITSET(29)
    #  define Fixed_Point_Bit_Position 29
    #elif //etc...
    

    【讨论】:

      猜你喜欢
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 2016-07-11
      相关资源
      最近更新 更多