web-dev-qa-db-ja.com

CまたはC ++でバイナリリテラルを使用できますか?

2進数で作業する必要があります。

私が書いてみました:

const x = 00010000;

しかし、うまくいきませんでした。

00010000と同じ値を持つ16進数を使用できることはわかっていますが、C++で2進数用の型があるかどうか、またそうでない場合は、別の解決策がありますか?

177
hamza

C++ 0xを待つ間に BOOST_BINARYを使用 できます。 :) BOOST_BINARYは、それが限りではテンプレート実装よりもおそらく利点がありますCプログラムでも使用できます(100%プリプロセッサ駆動)

更新

逆のことをする(すなわち、数値を2進形式で出力する)には、移植性のない itoa関数 、または 自分で実装します を使用できます。

残念ながら、STLストリームで基数2のフォーマットを行うことはできません( setbase は基数8、10、および16のみを尊重するため)、しかしstd::stringを使用できますitoaのバージョン、または(より簡潔ではあるが、わずかに効率が悪い)std::bitset

(ありがとうございました Rogerbitsetのヒントをありがとうございます!)

#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 Manor FarmのString Formattersも参考になります。

67
vladr

GCCを使用している場合は、 GCC拡張C++ 14規格 に含まれています)を使用できます。

int x = 0b00010000;
247
qrdl

バイナリリテラルを使うことができます。それらはC++ 14で標準化されています。例えば、

int x = 0b11000;

GCCでのサポート

GCCでのサポートはC言語ファミリの拡張としてGCC 4.3から始まりました( https://gcc.gnu.org/gcc-4.3/changes.html を参照)( 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++ を参照)。

76
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でなければなりません。

73
wilhelmtell

いくつかのコンパイラ(通常 microcontrollers 用のもの)は、数字の前に接頭辞 "0b ..."を付けてリテラル2進数を認識するように実装された特別な機能を持ちます。ほとんどのコンパイラ(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;

デメリット(それほど大きなものではありません):

  • 2進数は4 x 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のグループ化にも拡張可能)。
30

このスレッド 助けになるかもしれません。

/* 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に支払われます。)

20

すでに回答したように、C標準には2進数を直接書く方法がありません。ただし、コンパイラの拡張機能もあり、C++ 14にはバイナリの0bプレフィックスが含まれているようです。 (この答えはもともと2010年に投稿されたものです。)

よくある回避策の1つは、 ヘルパーマクロを含むヘッダーファイル を含めることです。簡単なオプションの1つは、8ビットパターンすべてのマクロ定義を含むファイルを生成することです。

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

その結果、256個の#definesしか必要とされず、8ビットを超えるバイナリ定数が必要な場合は、これらの定義をshiftやOR、場合によってはヘルパーマクロ(例えばBIN16(B00000001,B00001010))と組み合わせることができます。 (32ビットはもちろん、16ビットごとに個別のマクロを持つことは妥当ではありません。)

もちろん、この欠点はすべての先行ゼロを書く必要があることですが、これはビットフラグの設定やハードウェアレジスタの内容のような使用のためにより明確にするかもしれません。このプロパティがないと構文が生成される関数のようなマクロについては、上記のbithacks.hを参照してください。

15
Arkku

C++の過剰エンジニアリングの考え方は、ここで他の回答ですでによく説明されています。これは、C、keep-it-simple-ffsの考え方でやってみたものです。

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

Cは純粋な2進数に対してネイティブ表記をしていません。ここでの最善の策は、8進数(例:07777)または16進数(例:0xfff)のいずれかです。

12

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のようなことをすることができます。

9
Mark Ransom

使用できる最小単位はバイトです(これはchar型です)。ビット演算子を使用してビットを操作することもできます。

整数リテラルについては、10進数(基数10)、8進数(基数8)、または16進数(基数16)でのみ作業できます。 CにもC++にもバイナリ(基数2)リテラルはありません。

8進数の前には0が付き、16進数の前には0xが付きます。 10進数には接頭辞はありません。

C++ 0xでは、 ユーザー定義リテラル によって、やり方でやりたいことができるでしょう。

7
Brian R. Bondy

他の答えに基づいていますが、これは違法なバイナリリテラルを持つプログラムを拒否します。先行ゼロはオプションです。

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;
}
4
Thomas Eding

このようにインラインアセンブリを使用することもできます。

int i;

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

std::cout << i;

さて、それはやややり過ぎかもしれませんが、それは動作します:)

2
renger

2進数の「型」は、任意の10進数、16進数、または8進数と同じです。int(またはchar、short、long long)。

あなたが定数を割り当てるとき、あなたは11011011でそれを割り当てることはできません(不思議なことにそして残念ながら)、しかしあなたはhexを使うことができます。 16進数は精神的に翻訳するのが少し簡単です。ニブル(4ビット)単位でチャンクし、[0-9a-f]の文字に変換します。

2
Stephen

あなたはビットセットを使うことができます

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

私は@ 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; */
2
madmurphy

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ビットを意味します。

0
Hadi Rasekh