C binary literals
众所周知,C 语言中只有十进制、十六进制和八进制的常数表示(literal),没有二进制的常数表示。有时候我们很想用二进制的常数,因为它设置了哪些位一目了然。当然了,十六进制和八进制在某种程度上也行,对于熟练的人或许一眼就能看出,但是有二进制的常数表示不是更好嘛?
这里有人就给出了一个解决方法,构造一个宏接受二进制的“常量”,这样我们就可以通过它来直接使用二进制常量了。其实代码很容易理解,见下:
[c]
/ Binary constant generator macro
By Tom Torfs - donated to the public domain
/
/ All macro’s evaluate to compile-time constants /
/ ** helper macros */
/ turn a numeric literal into a hex constant
(avoids problems with leading zeroes)
8-bit constants max value 0x11111111, always fits in unsigned long
/
define HEX__(n) 0x##n##LU
/ 8-bit conversion function /
define B8__(x) ((x&0x0000000FLU)?1:0)
+((x&0x000000F0LU)?2:0)
+((x&0x00000F00LU)?4:0)
+((x&0x0000F000LU)?8:0)
+((x&0x000F0000LU)?16:0)
+((x&0x00F00000LU)?32:0)
+((x&0x0F000000LU)?64:0)
+((x&0xF0000000LU)?128:0)
/ ** user macros */
/ for upto 8-bit binary constants /
define B8(d) ((unsigned char)B8(HEX(d)))
/ for upto 16-bit binary constants, MSB first /
define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8)
+ B8(dlsb))
/ for upto 32-bit binary constants, MSB first /
define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24)
+ ((unsigned long)B8(db2)<<16)
+ ((unsigned long)B8(db3)<<8)
+ B8(dlsb))
/ Sample usage:
B8(01010101) = 85
B16(10101010,01010101) = 43605
B32(10000000,11111111,10101010,01010101) = 2164238933
/
[/c]
把这段代码放到头文件中,使用的时候 #include 进去就行了。当然了,这最好还是编译器支持才行,幸运的是,gcc 从4.3 开始就已经支持二进制常数了!以0b或者0B为前缀即可,比如:0b01010101。
示例代码如下:
[c]
include
int main(void)
{
assert(B8(01010101) == 85);
assert(B8(01010101) == 0b01010101); //gcc extension!!
assert(B8(11111111) == 0xff);
assert(B8(00111111) == 077);
assert(B16(10101010,01010101) == 43605);
assert(B32(10000000,11111111,10101010,01010101) == 2164238933);
return 0;
}
[/c]
顺便说一句,在C++中你可以使用 std::bitset。