问题
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