Macro to compute number of bits needed to store a number n

风格不统一 提交于 2020-01-13 08:13:10

问题


Let's say I need to write C macro that returns number of bits(1..32) needed to store unsigned 32-bit integer. (Result equals ceiling(log2(n)).

I need it as compile-time computed macro, not a function.

I could do

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

it works, but is rather long. (Speed does not matter here, computation is at compile time).

Is there shorter way to write this macro ? Shortest ?


回答1:


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

it is good?




回答2:


If you do not mind additional statements (while loop) the following will work in 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);

Output:

28
16
32
1




回答3:


This can be done with a macro that does a bit less test than what you propose in your question, by using a more clever bit testing for several bits at a time. The macro P99_HIGH2 from P99 implements such a trick as was already mentioned in one of the comments. If this is used for compile time expressions, there is no danger in evaluating the argument several times, since this must be an integer constant expression, anyhow.




回答4:


This is not a solution for C, but for C++ (c++11 or higher), constexpr instead of MACRO is a way to go.

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

The compiler will do evaluation at compile time and replace the call (e.g. log2(16)) with a literal value (e.g. 5), provided -O2 or -O3 optimization is used (because of the recursive call).




回答5:


I don't think the C preprocessor is able to do this. If I'm not mistaking, you can't place preprocessor if statements in a macro. All you can do is a piece of code with holes, with the parameters of the macro filling the holes.



来源:https://stackoverflow.com/questions/6834868/macro-to-compute-number-of-bits-needed-to-store-a-number-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!