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)&lt;&lt;16) 
            + ((unsigned long)B8(db3)&lt;&lt;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