我可以在 C 或 C++ 中使用二进制文字吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2611764/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I use a binary literal in C or C++?
提问by hamza
I need to work with a binary number.
我需要使用二进制数。
I tried writing:
我试着写:
const x = 00010000;
But it didn't work.
但它没有用。
I know that I can use an hexadecimal number that has the same value as 00010000
, but I want to know if there is a type in C++ for binary numbers and if there isn't, is there another solution for my problem?
我知道我可以使用与 具有相同值的十六进制数00010000
,但我想知道 C++ 中是否有二进制数的类型,如果没有,是否有其他解决方案可以解决我的问题?
采纳答案by vladr
You can use BOOST_BINARY
while waiting for C++0x. :) BOOST_BINARY
arguably has an advantage over template implementation insofar as it can be used in C programs as well(it is 100% preprocessor-driven.)
您可以使用BOOST_BINARY
在等待的C ++ 0x。:) BOOST_BINARY
可以说比模板实现有优势,因为它也可以在 C 程序中使用(它是 100% 预处理器驱动的。)
To do the converse (i.e. print out a number in binary form), you can use the non-portable itoa
function, or implement your own.
要进行相反的操作(即以二进制形式打印出一个数字),您可以使用不可移植itoa
函数,或者实现您自己的.
Unfortunately you cannot do base 2 formatting with STL streams (since setbase
will only honour bases 8, 10 and 16), but you canuse either a std::string
version of itoa
, or (the more concise, yet marginally less efficient) std::bitset
.
不幸的是,你不能做基地2 STL格式数据流(因为setbase
只会荣誉基地8,10和16),但你可以使用一个std::string
版本的itoa
,或者(更简洁,但稍微低效率)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;
}
produces:
产生:
hex: 0012, dec: 18, oct: 000022, bin: 10010
hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010
Also read Herb Sutter's The String Formatters of Manor Farmfor an interesting discussion.
另请阅读 Herb Sutter 的The String Formatters of Manor Farm进行有趣的讨论。
回答by qrdl
If you are using GCC then you can use a GCC extension(which is included in the C++14 standard) for this:
如果您使用 GCC,那么您可以为此使用GCC 扩展(包含在C++14 标准中):
int x = 0b00010000;
回答by Mohamed El-Nakib
You can use binary literals. They are standardized in C++14. For example,
您可以使用二进制文字。它们在 C++14 中标准化。例如,
int x = 0b11000;
Support in GCC
海湾合作委员会的支持
Support in GCC began in GCC 4.3 (see https://gcc.gnu.org/gcc-4.3/changes.html) as extensions to the C language family (see https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions), but since GCC 4.9 it is now recognized as either a C++14 feature or an extension (see Difference between GCC binary literals and C++14 ones?)
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 二进制文字之间的区别?)
Support in Visual Studio
Visual Studio 中的支持
Support in Visual Studio started in Visual Studio 2015 Preview (see https://www.visualstudio.com/news/vs2015-preview-vs#C++).
Visual Studio 中的支持始于 Visual Studio 2015 预览版(请参阅https://www.visualstudio.com/news/vs2015-preview-vs#C++)。
回答by wilhelmtell
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';
The leftmost digit of the literal still has to be 1, but nonetheless.
文字最左边的数字仍然必须是 1,但仍然如此。
回答by Renato Chandelier
A few compilers (usually the ones for microcontrollers) has a special feature implemented within recognizing literal binary numbers by prefix "0b..."preceding the number, although most compilers (C/C++ standards) don't have such feature and if it is the case, here it is my alternative solution:
一些编译器(通常是微控制器的编译器)具有通过数字前面的前缀“0b...”识别字面二进制数的特殊功能,尽管大多数编译器(C/C++ 标准)没有这样的功能,如果它是这样,这是我的替代解决方案:
#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;
Disadvantages(it's not such a big ones):
缺点(不是那么大):
- The binary numbers have to be grouped 4 by 4;
- The binary literals have to be only unsigned integer numbers;
- 二进制数必须按 4 × 4 分组;
- 二进制文字只能是无符号整数;
Advantages:
优点:
- Total preprocessor driven, not
spending processor time
in pointless operations (like "?.. :..", "<<", "+"
) to the executable program (it may be performed hundred of times in the final application); - It works
"mainly in C"
compilers and C++ as well (template+enum solution works only in C++ compilers
); - It has only the limitation of "longness" for expressing "literal constant" values. There would have been earlyish longness limitation (usually 8 bits: 0-255) if one had expressed constant values by parsing resolve of
"enum solution" (usually 255 = reach enum definition limit)
, differently, "literal constant" limitations, in the compiler allows greater numbers; - Some other solutions demand exaggerated number of constant definitions (too many defines in my opinion) including long or
several header files
(in most cases not easily readable and understandable, and make the project become unnecessarily confused and extended, like that using"BOOST_BINARY()"
); - Simplicity of the solution: easily readable, understandable and adjustable for other cases (could be extended for grouping 8 by 8 too);
- 完全由预处理器驱动,而不是对可执行程序
spending processor time
进行无意义的操作(like "?.. :..", "<<", "+"
)(在最终应用程序中可能会执行数百次); - 它也适用于
"mainly in C"
编译器和 C++ (template+enum solution works only in C++ compilers
); - 它只有表达“字面常量”值的“长度”限制。如果通过解析解析来表达常量值,那么早期的长度限制(通常是 8 位:0-255)
"enum solution" (usually 255 = reach enum definition limit)
,不同的是,“文字常量”限制,在编译器中允许更大的数字; - 其他一些解决方案需要夸大数量的常量定义(在我看来定义太多),包括 long or
several header files
(在大多数情况下不容易阅读和理解,并使项目变得不必要的混乱和扩展,就像使用"BOOST_BINARY()"
); - 解决方案的简单性:易读、易懂且可针对其他情况进行调整(也可以扩展为 8 乘 8 分组);
回答by Federico A. Ramponi
This threadmay help.
这个线程可能会有所帮助。
/* 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;
}
It works! (All the credits go to Tom Torfs.)
有用!(所有的功劳都归于 Tom Torfs。)
回答by Arkku
As already answered, the C standards have no way to directly write binary numbers. There are compiler extensions, however, and apparently C++14 includes the 0b
prefix for binary. (Note that this answer was originally posted in 2010.)
正如已经回答的那样,C 标准无法直接写入二进制数。然而,有编译器扩展,显然 C++14 包含0b
二进制的前缀。(请注意,此答案最初发布于 2010 年。)
One popular workaround is to include a header file with helper macros. One easy option is also to generate a file that includes macro definitions for all 8-bit patterns, e.g.:
一种流行的解决方法是包含一个带有帮助宏的头文件。一个简单的选择是生成一个包含所有 8 位模式的宏定义的文件,例如:
#define B00000000 0
#define B00000001 1
#define B00000010 2
…
This results in only 256 #define
s, and if larger than 8-bit binary constants are needed, these definitions can be combined with shifts and ORs, possibly with helper macros (e.g., BIN16(B00000001,B00001010)
). (Having individual macros for every 16-bit, let alone 32-bit, value is not plausible.)
这导致只有 256#define
秒,如果需要大于 8 位的二进制常量,这些定义可以与移位和 OR 组合,可能与辅助宏(例如,BIN16(B00000001,B00001010)
)。(每个 16 位都有单独的宏,更不用说 32 位了,价值是不合理的。)
Of course the downside is that this syntax requires writing all the leading zeroes, but this may also make it clearer for uses like setting bit flags and contents of hardware registers. For a function-like macro resulting in a syntax without this property, see bithacks.h
linked above.
当然,缺点是这种语法需要写入所有前导零,但这也可能使设置位标志和硬件寄存器内容等用途更加清晰。对于导致没有此属性的语法的类似函数的宏,请参阅bithacks.h
上面的链接。
回答by Craig
The C++ over-engineering mindset is already well accounted for in the other answers here. Here's my attempt at doing it with a C, keep-it-simple-ffs mindset:
此处的其他答案中已经很好地说明了 C++ 过度设计的心态。这是我尝试使用 C 语言,保持简单的 ffs 思维方式:
unsigned char x = 0xF; // binary: 00001111
回答by Nikolai Fetissov
C does not have nativenotation for pure binary numbers. Your best bet here would be either octal(e.g. 07777
) of hexadecimal(e.g. 0xfff
).
C 没有纯二进制数的原生符号。您最好的选择是八进制(例如07777
)或十六进制(例如0xfff
)。
回答by Mark Ransom
You can use the function found in this questionto get up to 22 bits in C++. Here's the code from the link, suitably edited:
您可以使用此问题中的函数在 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 } ;
};
So you can do something like binary<0101011011>::value
.
所以你可以做类似的事情binary<0101011011>::value
。