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

时间:2010-04-10 00:35:11

标签: c++ c binary

我需要使用二进制数。

我试着写:

const x = 00010000;

但它不起作用。

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

22 个答案:

答案 0 :(得分:247)

如果您正在使用GCC,那么您可以使用a GCC extensionthe C++14 standard中包含此内容):

int x = 0b00010000;

答案 1 :(得分:76)

您可以使用二进制文字。它们在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特性或者扩展(见Difference between GCC binary literals and C++14 ones?

Visual Studio中的支持

在Visual Studio 2015 Preview中启动Visual Studio支持(请参阅https://www.visualstudio.com/news/vs2015-preview-vs#C++)。

答案 2 :(得分: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';

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

答案 3 :(得分:67)

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

更新

要进行相反操作(即打印出二进制形式的数字),您可以使用不可移植的itoa functionimplement your own

不幸的是,您无法使用STL流进行基本2格式化(因为setbase只会标记基数8,10和16),但您可以使用std::string版本itoa的{​​{1}},或者{更简洁但效率稍低一点std::bitset

(感谢Roger了解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的 The String Formatters of Manor Farm 进行有趣的讨论。

答案 4 :(得分:30)

一些编译器(通常是microcontrollers的编译器)在通过前缀“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;

缺点(它不是那么大):

  • 二进制数必须按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),不同的是,“文字常量”限制,在编译器中允许更大的数字;
  • 其他一些解决方案要求夸大数量的常量定义(我认为定义太多),包括long或several header files(在大多数情况下不易读取和理解,并使项目变得不必要地混淆和扩展,就像那样使用"BOOST_BINARY()");
  • 解决方案的简单性:易于阅读,易于理解并可针对其他情况进行调整(也可以扩展为8个分组8个);

答案 5 :(得分:20)

This thread可能会有所帮助。

/* 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所有。)

答案 6 :(得分:15)

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

一种流行的解决方法是包含a header file with helper macros。一个简单的选择是生成一个包含所有8位模式的宏定义的文件,例如:

#define B00000000 0
#define B00000001 1
#define B00000010 2
…

这导致只有256 #define s,如果需要大于8位的二进制常量,这些定义可以与移位和OR组合,可能还有辅助宏(例如,BIN16(B00000001,B00001010)) 。 (每个16位都有单独的宏,更不用说32位值了。)

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

答案 7 :(得分:14)

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

unsigned char x = 0xF; // binary: 00001111

答案 8 :(得分:12)

对于纯二进制数,C没有 native 表示法。这里你最好的选择是八进制(例如07777十六进制(例如0xfff)。

答案 9 :(得分:9)

您可以使用找到的函数in this question在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之类的事情。

答案 10 :(得分:7)

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

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

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

在C ++ 0x中,你可以通过user defined literals的方式做你想做的事。

答案 11 :(得分:4)

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

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;
}

答案 12 :(得分:2)

您可以使用bitset

bitset<8> b(string("00010000"));
int i = (int)(bs.to_ulong());
cout<<i;

答案 13 :(得分:2)

你也可以像这样使用内联汇编:

int i;

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

std::cout << i;

好吧,这可能有点矫枉过正,但它有效:)

答案 14 :(得分:2)

二进制数的“类型”与任何十进制,十六进制或八进制数相同:int(甚至是char,short,long long)。

当你指定一个常量时,你不能用11011011(好奇和不幸)分配它,但你可以使用十六进制。 Hex更容易进行心理翻译。半字节(4位)中的块并转换为[0-9a-f]中的字符。

答案 15 :(得分:2)

我通过确保支持:

扩展了@ 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个小块作为参数

我实际上不太确定“quintibble”和“septibble”这两个词。如果有人知道任何替代方案,请告诉我。

这是重写的宏:

#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))

以下是雷纳托的例子:

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; */

答案 16 :(得分:0)

只需在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位,依此类推。

答案 17 :(得分:0)

这是我没有添加 Boost 库的函数:

用法:BOOST_BINARY(00010001);

int BOOST_BINARY(int a){
    int b = 0;
    
    for (int i = 0;i < 8;i++){
        b += a % 10 << i;
        a = a / 10;
    }
    
    return b;
}

答案 18 :(得分:0)

从 C++14 开始,您可以使用二进制文字,现在它们是语言的一部分:

unsigned char a = 0b00110011;

答案 19 :(得分:-1)

C ++提供了一个名为bitset的标准模板。如果你愿意,试试吧。

答案 20 :(得分:-1)

用法:BINARY(00010001);

int BINARY(int a){ int b = 0;

for (int i = 0;i < 8;i++){
    b += a % 10 << i;
    a = a / 10;
}

return b;

}

答案 21 :(得分:-8)

你可以尝试:

bool i[8] = {0,0,1,1,0,1,0,1}