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

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

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

我可以

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

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

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

 #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  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; } 

这好吗?

如果您不介意其他语句(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

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

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

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

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

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