用于计算存储数字n所需的位数的宏

时间:2011-07-26 18:40:08

标签: c macros c-preprocessor bits

假设我需要编写 C 宏,它返回存储无符号32位整数所需的位数(1..32)。 (结果等于上限(log2(n))。

我需要它作为编译时计算的宏,而不是函数。

我能做到

 #define NBITS(n) ((n)&(1<<31)?32:(n)&(1<<30)?31:...

它有效,但相当长。 (速度与此无关,计算在编译时)。

有没有更短的方法来编写这个宏?最短的?

5 个答案:

答案 0 :(得分:10)

#define NBITS2(n) ((n&2)?1:0)
#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n)))
#define NBITS8(n) ((n&0xF0)?(4+NBITS4(n>>4)):(NBITS4(n)))
#define NBITS16(n) ((n&0xFF00)?(8+NBITS8(n>>8)):(NBITS8(n)))
#define NBITS32(n) ((n&0xFFFF0000)?(16+NBITS16(n>>16)):(NBITS16(n)))
#define NBITS(n) (n==0?0:NBITS32(n)+1)
#include <iostream>
using namespace std;

int main(){
    cout << NBITS(0) << endl;
    cout << NBITS(1) << endl;
    cout << NBITS(2) << endl;
    cout << NBITS(3) << endl;
    cout << NBITS(4) << endl;
    cout << NBITS(1023) << endl;
    cout << NBITS(1024) << endl;
}

很好吗?

答案 1 :(得分:0)

如果您不介意其他语句(while循环),则以下内容适用于c99

#define NBITS_32(n,out_len) 0; while (n && !(0x80000000 >> out_len & n)) out_len++; out_len = n ? abs(out_len - 32) : n


uint8_t len1 = NBITS_32(0x0F000000, len1);
uint8_t len2 = NBITS_32(0x00008000, len2);
uint8_t len3 = NBITS_32(0xFFFFFFFF, len3);
uint8_t len4 = NBITS_32(0x00000001, len4);

printf("%u\n%u\n%u\n%u\n", len1, len2, len3, len4);

输出:

  

28
16
32
1

答案 2 :(得分:0)

这可以通过一个宏来完成,该宏比你在问题中建议的测试少一点,通过一次使用更聪明的位测试几个位。来自P99的宏P99_HIGH2实现了其中一条评论中已经提到过的技巧。如果这用于编译时表达式,那么多次计算参数就没有危险,因为无论如何这必须是一个整数常量表达式。

答案 3 :(得分:0)

这不是C的解决方案,但对于C ++(c ++ 11或更高版本),constexpr而不是MACRO是一种方法。

constexpr int log2(unsigned int word) {     
    return word ? (1 + log2(word>>1)) : 0; 
};

编译器将在编译时进行评估,并使用文字值(例如5)替换调用(例如log2(16)),前提是使用-O2或-O3优化(因为递归调用)。

答案 4 :(得分:-3)

我不认为C预处理器能够做到这一点。如果我没有误会,你不能在宏中放置预处理器if语句。你所能做的只是一段带孔的代码,宏的参数填满了孔。