【问题标题】:How does the compiler implement bit field arithmetics?编译器如何实现位域算术?
【发布时间】:2011-11-29 15:22:06
【问题描述】:

当问到如何做 wrapped N bit signed subtraction 的问题时,我得到了以下答案:

template<int bits>
int
sub_wrap( int v, int s )
{
    struct Bits { signed int r: bits; } tmp;
    tmp.r = v - s;
    return tmp.r;
}

这很简洁,但是编译器将如何实现呢?从this question 我收集到访问位字段与手动操作或多或少相同,但是当与本示例中的算术结合使用时呢?它会像手动旋转位一样快吗?

如果有人想具体一点,“编译器”角色的“gcc”答案会很好。我已经尝试阅读生成的程序集,但它目前超出了我的范围。

【问题讨论】:

  • 对于它的价值来说,这比手动编码的位旋转更难以阅读,即使它提高了性能我也会避免使用它(当然,除非这个单件位-杂乱无章的代码非常重要,它是性能的唯一瓶颈)。
  • 如果v-s 的值不能存储在tmp.r 中,我认为这实际上会调用未定义的行为(这意味着无论如何都不能保证它的位环绕效果)。
  • 唯一知道的方法是阅读编译器生成的汇编代码。
  • @AndréCaron 我不太了解“不可读”部分。这个变体清楚而准确地表明我们想要一个超过bits 位的结果。手工编码的旋转依赖于对某些编程模式的识别;大多数程序员可能不太熟悉的模式。因此,如果在生产代码中使用它需要大量注释(因为这个版本可以在没有注释的情况下进入)。
  • @JamesKanze:这个版本需要熟悉这种很少遇到的语法,这也是大多数程序员不太熟悉的编程模式,我不知道哪个鲜为人知。但是,(v-s) &amp; ((1&lt;&lt;bits)-1) 和一条评论说“将v-s 截断为bits 位”在我看来比使用位字段和隐式(可能不可靠)截断操作的本地struct 更明确.正如 Python 的禅宗所说,“显式胜于隐式”。

标签: c++ gcc bit-manipulation bit-fields


【解决方案1】:

正如另一个问题中所写,无符号包装数学可以这样完成:

int tmp = (a - b) & 0xFFF;  /* 12 bit mask.  */

写入到(12 位)位域将完全做到这一点,有符号或无符号。唯一的区别是您可能会收到来自编译器的警告消息。

对于阅读,你需要做一些不同的事情。

对于无符号数学,这样做就足够了:

int result = tmp;  /* whatever bit count, we know tmp contains nothing else.  */

int result = tmp & 0xFFF;  /* 12bit, again, if we have other junk in tmp.  */

对于有符号数学,额外的魔法是符号扩展:

int result = (tmp << (32-12)) >> (32-12); /* asssuming 32bit int, and 12bit value. */

所做的只是在更宽的整数中复制位域的最高位(位 11)。

这正是编译器对位域所做的。是手动编码还是位域编码取决于您,但请确保您获得正确的幻数。

(我没有阅读标准,但我怀疑依靠位域在溢出时做正确的事情可能不安全?)

【讨论】:

    【解决方案2】:

    编译器知道您的示例中r 的大小和确切位置。假设是这样的

    [xxxxrrrr]
    

    然后

    tmp.r = X;
    

    例如可以扩展为(表示二进制字面量的 b 后缀,&amp; 是按位,| 是按位或)

    tmp = (tmp & 11110000b)   // <-- get the remainder which is not tmp.r
        | (X   & 00001111b);  // <-- put X into tmp.r and filter away unwanted bits
    

    想象一下你的布局是

    [xxrrrrxx]   // 4 bits, 2 left-shifts
    

    扩展可能是

    tmp = (tmp    & 11000011b)   // <-- get the remainder which is not tmp.r
        | ((X<<2) & 00111100b);  // <-- filter 4 relevant bits, then shift left 2
    

    X 的实际外观如何,无论是复杂的表述还是文字,实际上都无关紧要。

    如果您的架构不支持这种按位运算,仍然存在乘以和除以 2 的幂来模拟移位,并且可能这些也可以用来过滤掉不需要的位。

    【讨论】:

      猜你喜欢
      • 2016-01-02
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      相关资源
      最近更新 更多