我可以在C或C ++中使用二进制文字吗?
我需要使用二进制数字。
我试着写:
const x = 00010000;
但它没有工作。
我知道我可以使用与00010000
具有相同值的十六进制数字,但是我想知道在C ++中是否存在二进制数字类型,如果没有,是否有另一种解决方案?
您可以在等待C ++ 0x时使用BOOST_BINARY
。 🙂 BOOST_BINARY
可以说比模板实现有优势,因为它也可以在C程序中使用 (它是100%预处理器驱动的)。
UPDATE
为了做相反的处理(即以二进制形式打印出一个数字),你可以使用不可移植的itoa
函数 ,或者实现你自己的 。
不幸的是,你不能使用STL流做基2格式化(因为setbase
只会setbase
和16),但是你可以使用itoa
的std::string
版本,或者(更简洁但效率更低的) std::bitset
。
(感谢罗杰的小提示!)
#include <boost/utility/binary.hpp> #include <stdio.h> #include <stdlib.h> #include <bitset> #include <iostream> #include <iomanip> using namespace std; int main() { unsigned short b = BOOST_BINARY( 10010 ); char buf[sizeof(b)*8+1]; printf("hex: %04x, dec: %u, oct: %06o, bin: %16s\n", b, b, b, itoa(b, buf, 2)); cout << setfill('0') << "hex: " << hex << setw(4) << b << ", " << "dec: " << dec << b << ", " << "oct: " << oct << setw(6) << b << ", " << "bin: " << bitset< 16 >(b) << endl; return 0; }
生产:
hex: 0012, dec: 18, oct: 000022, bin: 10010 hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010
还请阅读Herb Sutter的“庄园农场的字符串格式”作一个有趣的讨论。
如果您使用的是GCC,那么您可以使用GCC扩展 (包含在C ++ 14标准中 ):
int x = 0b00010000;
template<unsigned long N> struct bin { enum { value = (N%10)+2*bin<N/10>::value }; } ; template<> struct bin<0> { enum { value = 0 }; } ; // ... std::cout << bin<1000>::value << '\n';
文字的最左边的数字仍然是1,但仍然是。
你可以使用二进制文字。 它们在C ++ 14中被标准化。 例如,
int x = 0b11000;
支持GCC
GCC支持从GCC 4.3开始(参见https://gcc.gnu.org/gcc-4.3/changes.html ),作为C语言家族的扩展(请参阅https://gcc.gnu.org/onlinedocs/gcc/ C-Extensions.html#C-Extensions ),但是从GCC 4.9开始,它现在被认为是C ++ 14特性或扩展(请参阅GCC二进制文字和C ++ 14之间的区别? )
在Visual Studio中支持
在Visual Studio 2015 Preview中启动了支持(请参阅https://www.visualstudio.com/news/vs2015-preview-vs#C++ )。
尽管大多数编译器(C / C ++标准)没有这样的特性,但是一些编译器(通常是用于微控制器的编译器)在识别文字二进制数字前加了一个特殊的功能,其前缀“0b …”是这样的,这里是我的替代解决方案:
#define B_0000 0 #define B_0001 1 #define B_0010 2 #define B_0011 3 #define B_0100 4 #define B_0101 5 #define B_0110 6 #define B_0111 7 #define B_1000 8 #define B_1001 9 #define B_1010 a #define B_1011 b #define B_1100 c #define B_1101 d #define B_1110 e #define B_1111 f #define _B2H(bits) B_##bits #define B2H(bits) _B2H(bits) #define _HEX(n) 0x##n #define HEX(n) _HEX(n) #define _CCAT(a,b) a##b #define CCAT(a,b) _CCAT(a,b) #define BYTE(a,b) HEX( CCAT(B2H(a),B2H(b)) ) #define WORD(a,b,c,d) HEX( CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))) ) #define DWORD(a,b,c,d,e,f,g,h) HEX( CCAT(CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))),CCAT(CCAT(B2H(e),B2H(f)),CCAT(B2H(g),B2H(h)))) ) // Using example char b = BYTE(0100,0001); // Equivalent to b = 65; or b = 'A'; or b = 0x41; unsigned int w = WORD(1101,1111,0100,0011); // Equivalent to w = 57155; or w = 0xdf43; unsigned long int dw = DWORD(1101,1111,0100,0011,1111,1101,0010,1000); //Equivalent to dw = 3745774888; or dw = 0xdf43fd28;
缺点 (这不是一个很大的):
- 二进制数字必须分4到4;
- 二进制文字只能是无符号整数;
优点 :
- 总预处理器驱动,而不是在可执行程序(在最终应用程序中可以执行数百次)中将毫无意义的操作(
like "?.. :..", "<<", "+"
)spending processor time
。 - 它
"mainly in C"
编译器和C ++(template+enum solution works only in C++ compilers
); - 它只有表达“文字常量”值的“长”的限制。 如果通过解析
"enum solution" (usually 255 = reach enum definition limit)
的解析"enum solution" (usually 255 = reach enum definition limit)
表示常量值,那么将会有早期的长度限制(通常是8位:0-255"enum solution" (usually 255 = reach enum definition limit)
,不同的是,“文字常量”限制编译器允许更多数字; - 一些其他的解决方案需要过多的常量定义(在我看来太多的定义),包括长或
several header files
(在大多数情况下不容易阅读和理解,并使项目变得不必要的混淆和扩展,就像使用"BOOST_BINARY()"
); - 简单的解决方案:易于阅读,可理解和可调整的其他情况下(也可以扩展为8×8组)。
这个线程可能有帮助。
/* Helper macros */ #define HEX__(n) 0x##n##LU #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 */ #define B8(d) ((unsigned char)B8__(HEX__(d))) #define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \ + B8(dlsb)) #define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \ + ((unsigned long)B8(db2)<<16) \ + ((unsigned long)B8(db3)<<8) \ + B8(dlsb)) #include <stdio.h> int main(void) { // 261, evaluated at compile-time unsigned const number = B16(00000001,00000101); printf("%d \n", number); return 0; }
有用! (所有的学分都去了Tom Torfs。)
正如已经回答的那样,C标准没有办法直接编写二进制数字。 有编译器扩展,但是,显然C ++ 14包含二进制的0b
前缀。 (请注意,这个答案最初是2010年发布的。)
一个流行的解决方法是包含一个带有助手宏的头文件 。 一个简单的选择是生成一个包含所有8位模式的宏定义的文件,例如:
#define B00000000 0 #define B00000001 1 #define B00000010 2 …
这只会导致256个#定义,如果需要大于8位的二进制常量,这些定义可以与移位和OR(可能带有助手宏)(如BIN16(B00000001,B00001010)
)组合使用。 (每个16位都有单独的宏,更不用说32位了,值是不合理的。)
当然,缺点是这个语法要求写所有的前导零,但是这也可以使设置位标志和硬件寄存器的内容更清晰。 对于没有这个属性的类似于函数的宏,请参阅bithacks.h
链接的bithacks.h
。
C没有纯二进制数的本机符号。 这里最好的选择是十六进制的八进制 (例如07777
)(例如0xfff
)。
C ++的过度工程思维已经在这里的其他答案中得到很好的解释。 这是我用C,keep-it-simple-ffs的心态做的尝试:
unsigned char x = 0xF; // binary: 00001111
你可以使用在这个问题中找到的函数在C ++中获得高达22位。 以下是链接中的代码,经过适当编辑:
template< unsigned long long N > struct binary { enum { value = (N % 8) + 2 * binary< N / 8 > :: value } ; }; template<> struct binary< 0 > { enum { value = 0 } ; };
所以你可以做一些像binary<0101011011>::value
。
您可以使用的最小单位是一个字节(它是char
类型的)。 尽管可以使用按位运算符来处理位。
至于整数文字,您只能使用十进制(基数10),八进制(基数8)或十六进制(基数16)数字。 在C和C ++中都没有二进制(基2)文字。
八进制数字前缀为0
,十六进制数字前缀为0x
。 十进制数字没有前缀。
在C ++ 0x中,你将能够通过用户定义的文字方式做你想做的事情。
根据其他一些答案,但是这个会拒绝带有非法二进制文字的程序。 前导零是可选的。
template<bool> struct BinaryLiteralDigit; template<> struct BinaryLiteralDigit<true> { static bool const value = true; }; template<unsigned long long int OCT, unsigned long long int HEX> struct BinaryLiteral { enum { value = (BinaryLiteralDigit<(OCT%8 < 2)>::value && BinaryLiteralDigit<(HEX >= 0)>::value ? (OCT%8) + (BinaryLiteral<OCT/8, 0>::value << 1) : -1) }; }; template<> struct BinaryLiteral<0, 0> { enum { value = 0 }; }; #define BINARY_LITERAL(n) BinaryLiteral<0##n##LU, 0x##n##LU>::value
例:
#define B BINARY_LITERAL #define COMPILE_ERRORS 0 int main (int argc, char ** argv) { int _0s[] = { 0, B(0), B(00), B(000) }; int _1s[] = { 1, B(1), B(01), B(001) }; int _2s[] = { 2, B(10), B(010), B(0010) }; int _3s[] = { 3, B(11), B(011), B(0011) }; int _4s[] = { 4, B(100), B(0100), B(00100) }; int neg8s[] = { -8, -B(1000) }; #if COMPILE_ERRORS int errors[] = { B(-1), B(2), B(9), B(1234567) }; #endif return 0; }
二进制数的“类型”与任何十进制,十六进制或八进制数相同: int
(或者甚至是char,short,long long)。
当你分配一个常量时,你不能用11011011(好奇而不幸地)分配它,但是你可以使用十六进制。 十六进制在智力上翻译起来要容易一些。 大块半字节(4位)并转换为[0-9a-f]中的字符。
你也可以像这样使用内联汇编:
int i; __asm { mov eax, 00000000000000000000000000000000b mov i, eax } std::cout << i;
好吧,这可能有点矫枉过正,但它的工作:)
你可以使用一个bitset
bitset<8> b(string("00010000")); int i = (int)(bs.to_ulong()); cout<<i;
只需使用C ++中的标准库:
#include <bitset>
你需要一个类型为std::bitset
的变量:
std::bitset<8ul> x; x = std::bitset<8>(10); for (int i = x.size() - 1; i >= 0; i--) { std::cout << x[i]; }
在这个例子中,我在x中存储了10的二进制。
8ul
定义了你的位的大小,所以7ul
表示7位,等等。
我通过确保以下方面的支持扩展了@ renato-chandelier给出的良好答复:
-
_NIBBLE_(…)
– 4位,1位半字节作为参数 -
_BYTE_(…)
– 8位,2个半字节作为参数 -
_SLAB_(…)
– 12位,3个半字节作为参数 -
_WORD_(…)
– 16位,4个半字节作为参数 -
_QUINTIBBLE_(…)
– 20位,5个半字节作为参数 -
_DSLAB_(…)
– 24位,6个半字节作为参数 -
_SEPTIBBLE_(…)
– 28位,7个半字节作为参数 -
_DWORD_(…)
– 32位,8个半字节作为参数
其实我不太确定“精确”和“可判断”这两个术语。 如果有人知道任何其他方式,请让我知道。
这是宏重写:
#define __CAT__(A, B) A##B #define _CAT_(A, B) __CAT__(A, B) #define __HEX_0000 0 #define __HEX_0001 1 #define __HEX_0010 2 #define __HEX_0011 3 #define __HEX_0100 4 #define __HEX_0101 5 #define __HEX_0110 6 #define __HEX_0111 7 #define __HEX_1000 8 #define __HEX_1001 9 #define __HEX_1010 a #define __HEX_1011 b #define __HEX_1100 c #define __HEX_1101 d #define __HEX_1110 e #define __HEX_1111 f #define _NIBBLE_(N1) _CAT_(0x, _CAT_(__HEX_, N1)) #define _BYTE_(N1, N2) _CAT_(_NIBBLE_(N1), _CAT_(__HEX_, N2)) #define _SLAB_(N1, N2, N3) _CAT_(_BYTE_(N1, N2), _CAT_(__HEX_, N3)) #define _WORD_(N1, N2, N3, N4) _CAT_(_SLAB_(N1, N2, N3), _CAT_(__HEX_, N4)) #define _QUINTIBBLE_(N1, N2, N3, N4, N5) _CAT_(_WORD_(N1, N2, N3, N4), _CAT_(__HEX_, N5)) #define _DSLAB_(N1, N2, N3, N4, N5, N6) _CAT_(_QUINTIBBLE_(N1, N2, N3, N4, N5), _CAT_(__HEX_, N6)) #define _SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7) _CAT_(_DSLAB_(N1, N2, N3, N4, N5, N6), _CAT_(__HEX_, N7)) #define _DWORD_(N1, N2, N3, N4, N5, N6, N7, N8) _CAT_(_SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7), _CAT_(__HEX_, N8))
这里是Renato使用的例子:
char b = _BYTE_(0100, 0001); /* equivalent to b = 65; or b = 'A'; or b = 0x41; */ unsigned int w = _WORD_(1101, 1111, 0100, 0011); /* equivalent to w = 57155; or w = 0xdf43; */ unsigned long int dw = _DWORD_(1101, 1111, 0100, 0011, 1111, 1101, 0010, 1000); /* Equivalent to dw = 3745774888; or dw = 0xdf43fd28; */
C ++提供了一个名为bitset
的标准模板。 试试看,如果你喜欢。
你可以尝试:
bool i[8] = {0,0,1,1,0,1,0,1}