我可以在C或C++中使用二进制文字吗?

ham*_*mza 182 c c++ binary

我需要使用二进制数.

我试着写:

const x = 00010000;
Run Code Online (Sandbox Code Playgroud)

但它没有用.

我知道我可以使用具有相同值的十六进制数字00010000,但我想知道C++中是否存在二进制数的类型,如果没有,是否有另一种解决方案可以解决我的问题?

qrd*_*rdl 260

如果您正在使用GCC,那么您可以使用GCC扩展(包含在C++ 14标准中):

int x = 0b00010000;
Run Code Online (Sandbox Code Playgroud)

  • 它适用于Clang,GCC和TCC.它在PCC中不起作用.我没有任何其他编译器来测试. (13认同)
  • 我见过许多支持它的嵌入式系统编译器.我不知道它应该是标准语言功能的任何特殊原因. (6认同)
  • @polemon http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf(C++ 14.) (5认同)
  • 将此标准化很好,但clang支持相同的表示法. (4认同)
  • 其他几个编译器在基数2中具有表达数字的这种或其他类似方式. (2认同)
  • 为了记录,遗憾的是MSVC2010不支持这一点. (2认同)

Muh*_*eeb 86

您可以使用二进制文字.它们在C++ 14中标准化.例如,

int x = 0b11000;
Run Code Online (Sandbox Code Playgroud)

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中的支持在Visual Studio 2015 Preview中启动(请参阅https://www.visualstudio.com/news/vs2015-preview-vs#C++).

  • 您可以使用'分隔每个部分:“ 0b0000'0100'0100'0001 (2认同)
  • @camino 很好,你可以失去第一个“ (2认同)
  • 这应该是公认的答案。大多数其他答案都已经过时了。 (2认同)

wil*_*ell 73

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';
Run Code Online (Sandbox Code Playgroud)

文字的最左边数字仍然必须是1,但仍然是.

  • 更好的版本:http://bitbucket.org/kniht/scraps/src/tip/cpp/binary.hpp(`binary <10> :: value == binary <010> :: value`和一些错误检查) (4认同)
  • 此模板创意的更好版本:http://code.google.com/p/cpp-binary-constants/ (4认同)

vla*_*adr 70

您可以使用BOOST_BINARY在等待的C++ 0x.:) BOOST_BINARY可以说比模板实现有优势,因为它也可以在C程序中使用(它是100%预处理器驱动的.)

UPDATE

要进行相反(即以二进制形式打印数字),您可以使用非便携式itoa功能,或实现自己的功能.

不幸的是,你不能做基地2 STL格式数据流(因为setbase只兑现基地8,10和16),但你可以使用一个std::string版本的itoa,或者(更简洁,但稍微低效率)std::bitset.

(谢谢你罗杰BOOST_BINARY提示!)

#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;
}
Run Code Online (Sandbox Code Playgroud)

生产:

hex: 0012, dec: 18, oct: 000022, bin:            10010
hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010
Run Code Online (Sandbox Code Playgroud)

另请阅读Herb Sutter的The Manor Formatters of Manor Farm进行有趣的讨论.

  • 作为您链接的页面,您只能使用8,10或16与setbase.但是:`int main(){cout << bitset <8>(42); }` (2认同)

小智 30

一些编译器(通常是微控制器的编译器)具有一个特殊功能,通过前缀"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;
Run Code Online (Sandbox Code Playgroud)

缺点(它不是那么大):

  • 二进制数必须按4乘4分组;
  • 二进制文字必须只是无符号整数;

优点:

  • 总预处理器驱动,而不是对可执行程序的spending processor time无意义操作(like "?.. :..", "<<", "+")(在最终应用程序中可能执行了数百次);
  • 它也适用于"mainly in C"编译器和C++(template+enum solution works only in C++ compilers);
  • 它仅具有表示"文字常数"值的"长度"的限制.如果通过解析"enum solution" (usually 255 = reach enum definition limit)不同的"文字常量"限制来表示常量值,那么就会有早期的长度限制(通常是8位:0-255),在编译器中允许更大的数字;
  • 其他一些解决方案需要夸大的常量定义(我认为定义太多),包括长或several header files(在大多数情况下不易读取和理解,并使项目变得不必要地混淆和扩展,如使用"BOOST_BINARY()");
  • 解决方案的简单性:易于阅读,易于理解,并且可以针对其他情况进行调整(也可以扩展为8个分组);


Fed*_*oni 20

这个帖子可能有帮助.

/* 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;
}
Run Code Online (Sandbox Code Playgroud)

有用!(所有学分都归Tom Torfs所有.)

  • @Federico:`##`预处理器操作符将标记粘贴在一起.所以,在这种情况下,如果你调用`HEX __(10)`,它会扩展为`0x10LU`. (8认同)
  • B8宏通过将"二进制"文字转换为十六进制文字并提取每第4位来工作. (3认同)

Ark*_*kku 16

如前所述,C标准无法直接写入二进制数.但是,有编译器扩展,显然C++ 14包含0b二进制的前缀.(请注意,此答案最初发布于2010年.)

一种流行的解决方法是包含带辅助宏的头文件.一个简单的选择是生成一个包含所有8位模式的宏定义的文件,例如:

#define B00000000 0
#define B00000001 1
#define B00000010 2
…
Run Code Online (Sandbox Code Playgroud)

这导致仅256 #define秒,并且如果需要大于8位二进制常量,则这些定义可以与移位和OR组合,可能与辅助宏(例如,BIN16(B00000001,B00001010))一起.(每个16位具有单独的宏,更不用说32位值,这是不可信的.)

当然,缺点是这种语法需要写入所有前导零,但这也可以使其更清晰地用于设置位标志和硬件寄存器的内容.对于类似函数的宏,导致语法没有此属性,请参阅bithacks.h上面的链接.

  • @wilhelmtell:当我指定"所有*8位*模式"(= 256行)时,它的相关性是什么,并建议组合更大的数量?即使接受的答案的BOOST_BINARY也定义了标题中的所有8位模式...... (3认同)
  • 那么,如果你有一个`long long int`的所有宏,CPP需要读取多大的文件? (2认同)

小智 15

在这里的其他答案中已经充分考虑了C++过度工程的思维方式.这是我尝试使用C,keep-it-simple-ffs心态来做到这一点:

unsigned char x = 0xF; // binary: 00001111
Run Code Online (Sandbox Code Playgroud)


Nik*_*sov 12

C没有纯二进制数的本机表示法.在这里您最好的选择是,要么八进制(例如07777)的十六进制(例如0xfff).


Mar*_*som 10

您可以使用此问题中的函数在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 } ;
};
Run Code Online (Sandbox Code Playgroud)

所以你可以做点什么binary<0101011011>::value.


Bri*_*ndy 7

您可以使用的最小单位是一个字节(char类型).您可以通过使用按位运算符来处理位.

对于整数文字,您只能使用十进制(基数10),八进制(基数8)或十六进制(基数16)数字.C和C++中没有二进制(基数2)文字.

八进制数字以前缀为前缀,0十六进制数字以前缀为前缀0x.十进制数字没有前缀.

在C++ 0x中,您将能够通过用户定义的文字来执行您想要的操作.

  • 一些C编译器支持0b100101用于二进制文字,但遗憾的是它是非标准扩展. (5认同)
  • 请注意,虽然它没有在标准中定义,但是为了方便起见,一些编译器(特别是微控制器和嵌入式系统的编译器)以"0b00101010"的形式添加二进制语法.SDCC就是其中之一,我相信还有其他人也会这样做.(编辑:哈,打我吧,@乔伊!) (3认同)

Tho*_*ing 5

基于其他一些答案,但这个答案将拒绝具有非法二进制文字的程序。前导零是可选的。

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
Run Code Online (Sandbox Code Playgroud)

例子:

#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;
}
Run Code Online (Sandbox Code Playgroud)


ren*_*ger 5

您还可以像这样使用内联汇编:

int i;

__asm {
    mov eax, 00000000000000000000000000000000b
    mov i,   eax
}

std::cout << i;
Run Code Online (Sandbox Code Playgroud)

好吧,这可能有点矫枉过正,但它确实有效。

  • 您的解决方案不是多平台的。在许多体系结构中,您不能在 C 中包含汇编代码。特别是在 Microsoft Visual Studio 编译器中,您可以(针对 x86 32 位编译时)。但是你怎么知道你的处理器是否有“eax”寄存器?想想手机中的 ARM 处理器、x64 处理器等。它们没有“eax”。MIPS 处理器甚至没有命令“mov” (4认同)