你能在#defines / preprocessor指令中执行固定长度的位反转吗?

时间:2013-10-25 14:56:33

标签: c bit-manipulation c-preprocessor

我正在为ROM非常有限的目标编写 C 代码(不是c ++),但我希望使用#defines为其他类似目标轻松定制代码。我有#defines用于指定设备的地址和其他值,但作为一种代码保存技术,这些值必须按位反转。我可以通过先手动反转它们来输入这些,但这对将来使用会很困惑。我可以定义某种执行按位反转的宏吗?

4 个答案:

答案 0 :(得分:3)

如此处所示(Best Algorithm for Bit Reversal ( from MSB->LSB to LSB->MSB) in C),在c中切换顺序没有单一操作。因此,如果您要创建一个#define宏来执行操作,它实际上会在每次使用时执行相当多的工作(如果经常使用,则会显着增加二进制文件的大小)。我建议手动创建另一个有序常量,并使用清晰的文档来确保它们的信息不会丢失。

答案 1 :(得分:1)

为了可读代码,我不推荐它,但你可以做类似的事情

#define NUMBER 2

#define BIT_0(number_) ((number_ & (1<<0)) >> 0)
#define BIT_1(number_) ((number_ & (1<<1)) >> 1)

#define REVERSE_BITS(number_) ((BIT_1(number_) << 0) + (BIT_0(number_) << 1))

int main() {

    printf("%d --> %d", NUMBER, REVERSE_BITS(NUMBER));

}

答案 2 :(得分:1)

有这种操作的技术(例如,请参阅Boost Preprocessor库),但大多数情况下最简单的解决方案是使用以某种语言编写的外部预处理器,其中位操作更容易。

例如,这里有一个小python脚本,它将替换@REV(xxxx)@的所有实例,其中xxxx是一个十六进制字符串,其位反转常量具有相同的长度:

#!/bin/python
import re
import sys

reg = re.compile("""@REV\(([0-9a-fA-F]+)\)@""")
def revbits(s):
  return "0X%x" % int(bin(int(s, base=16))[-1:1:-1].ljust(4*len(s), '0'), base=2)

for l in sys.stdin:
  sys.stdout.write(reg.sub(lambda m: revbits(m.group(1)), l))

这是awk中的一个版本:

awk 'BEGIN{R["0"]="0";R["1"]="8";R["2"]="4";R["3"]="C";
           R["4"]="2";R["5"]="A";R["6"]="6";R["7"]="E";
           R["8"]="1";R["9"]="9";R["A"]="5";R["B"]="D";
           R["C"]="3";R["D"]="B";R["E"]="7";R["F"]="F";
           R["a"]="5";R["b"]="D";R["c"]="3";R["d"]="B";
           R["e"]="7";R["f"]="F";}

     function bitrev(x,    i, r) {
       r = ""
       for (i = length(x); i; --i)
         r = r R[substr(x,i,1)]
       return r 
     }
     {while (match($0, /@REV\([[:xdigit:]]+\)@/))
        $0 = substr($0, 1, RSTART-1) "0X" bitrev(substr($0, RSTART+5, RLENGTH-7)) substr($0, RSTART+RLENGTH)
     }1' \
     <<<"foo @REV(23)@ yy @REV(9)@ @REV(DEADBEEF)@"
foo 0X32 yy 0X9 0Xfeebdaed

答案 3 :(得分:0)

我认为这样的事情应该有效:

#define REV2(x)  ((((x)&1)<<1) | (((x)>>1)&1))
#define REV4(x)  ((REV2(x)<<2) | (REV2((x)>>2)))
#define REV8(x)  ((REV4(x)<<4) | (REV4((x)>>4)))
#define REV16(x) ((REV8(x)<<8) | (REV8((x)>>8)))
#define REV32(x) ((REV16(x)<<16) | (REV16((x)>>16)))

它只使用对常量表达式都安全的简单操作,编译器很可能会在编译时对它们进行评估。

您可以确保在编译时通过在需要常量表达式的上下文中使用它们来评估它们。例如,您可以初始化静态变量或声明枚举:

enum {
    VAL_A = SOME_NUMBER,
    LAV_A = REV32(VAL_A),
};