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


190

2進数を処理する必要があります。

私は書いてみました:

const x = 00010000;

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

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


51
あなたはそれ00010000が8進数だと知っていますよね?(そして、あなたの宣言には型が欠けています。)
キース・トンプソン

ここで C ++リテラルを使用する現代的な方法。
Lol4t0 2013年

2
C ++ 14はこのための機能を追加しました。下部の詳細については、私の新しい回答を参照してください。もちろん、それを実装するコンパイラが必要です。
lpapp 2013

1
@FormlessCloud:これらは、CおよびC ++標準で指定されている構文規則です(0bC ++ 14でのみ表示されます)。それらは明確になるように設計されています。
Keith Thompson

回答:


70

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

逆を行う(つまり、数値をバイナリ形式で出力する)には、非ポータブルitoa関数を使用するか、独自のを実装します

残念ながら、あなたは(以降STLストリームでフォーマットベース2を行うことができない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;
}

生成する:

hex: 0012, dec: 18, oct: 000022, bin:            10010
hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010

興味深い議論については、ハーブサッターのマナーファームの文字列フォーマッターもご覧ください


2
リンク先のページにあるとおり、setbaseで使用できるのは8、10、または16だけです。しかし:int main() { cout << bitset<8>(42); }

@ロジャーはヒントをありがとう、私はあなたのコメントを見る前にbitsetすでに少し修正しましたsetbase
vladr 2010

c ++ 11のユーザー定義リテラルに関するチュートリアルは次のとおりです:akrzemi1.wordpress.com/2012/10/23/user-defined-literals-part-ii。明らかにc ++ 1y(別名c ++ 14)は、標準にバイナリリテラルを含みます。
cheshirekow

274

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

int x = 0b00010000;

2
いくつかの他のコンパイラは、ベース2の数字を表現するこの又は他の同様の方法有する
nategoose

4
これを標準化しておくと便利ですが、clangも同じ表記をサポートしています。
ポールモン

14
Clang、GCC、TCCで動作します。PCCでは機能しません。テストできるコンパイラは他にありません。
Michas、2011年

6
私はそれをサポートする多くの組み込みシステムコンパイラを見てきました。標準の言語機能にすべきでない特別な理由はわかりません。
スーパーキャット2011


98

バイナリリテラルを使用できます。C ++ 14で標準化されています。例えば、

int x = 0b11000;

GCCでのサポート

GCCでのサポートは、C言語ファミリ(https://gcc.gnu.org/onlinedocs/gcc/を参照)の拡張機能としてGCC 4.3(https://gcc.gnu.org/gcc-4.3/changes.htmlを参照)から始まりました。 C-Extensions.html#C-Extensions)、ただしGCC 4.9以降、C ++ 14機能または拡張機能として認識されるようになりました(GCCバイナリリテラルとC ++ 14機能の違いを参照)。

Visual Studioでのサポート

Visual Studio 2015 Previewで開始されたVisual Studioのサポート(https://www.visualstudio.com/news/vs2015-preview-vs#C++を参照)。


5
'を使用して各部分を区切ることができます: "0b0000'0100'0100'0001
camino

1
@caminoニース、最初のものを失うことができます "
Nikos

これは受け入れられる答えになるはずです。他の答えのほとんどはすごく時代遅れです。
Alex

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でなければなりませんが、それでもなおです。


4
より良いバージョン:bitbucket.org/kniht/scraps/src/tip/cpp/binary.hppbinary<10>::value == binary<010>::valueおよびいくつかのエラーチェック)

私が自分のほぼ同じ答えを投稿する前に、どういうわけかこれを逃しました。しかし、鉱山で有数の桁が0でなく、1である必要があります
マーク身代金

4
このテンプレートのアイデアのより良いバージョン:code.google.com/p/cpp-binary-constants
Valentin Galea

@ValentinGalea-なぜこれよりもグーグルバージョンが良いのですか?
AJed 2016年

これは驚異的な印象です。残念ながら、ビット数が多くても機能しません。
量子物理学者

31

いくつかのコンパイラ(のための通常のもののマイクロコントローラ)によってリテラル進数を認識内に実装され、特別な機能がある「... 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;

短所(それほど大きなものではありません):

  • 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)がありました。
  • 他のいくつかのソリューションは、長いまたはseveral header files(ほとんどの場合、簡単に読みやすく、理解できない)を含む定数定義の誇張(私の意見では定義が多すぎる)を要求し、プロジェクトを使用するように、不必要に混乱させたり拡張したりし"BOOST_BINARY()"ます。
  • ソリューションのシンプルさ:他の場合でも読みやすく、理解しやすく、調整可能(8 x 8のグループにも拡張可能)。

なぜ(たとえばのB_0100代わりに0100)使用されないのですか?例えばのようにchar b = BYTE(0100,0001);
Peter Mortensen

@PeterMortensen B_は、_B2Hプリプロセッサ関数によって追加されます。
mxmlnkn 2017年

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

できます!(すべてのクレジットはTom Torfsに送られます。)


私は本当に理解していませんでしたが(プログラミングの初心者、特にC ++で)、興味深いようですので、C ++の研究をさらに進めた後で理解しようと思います。ありがとう
hamza

3
B8マクロは、「バイナリ」リテラルを16進リテラルに変換し、4ビットごとに抽出することによって機能します。
dan04

0x ## n ## LUはどういう意味ですか?そのような構文に遭遇したことはありません。
フェデリコA.ランポーニ2010

@hamza:確かにかなり複雑です。ただし、理解する必要があるのは、#include <stdio>以降だけです。
フェデリコA.ランポーニ2010

8
@Federico:##プリプロセッサーのオペレーターがトークンを貼り付けます。したがって、この場合、を呼び出すとHEX__(10)、に展開され0x10LUます。
James McNellis、

18

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

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

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

これは256 #define秒しか発生せず、8ビットより大きいバイナリ定数が必要な場合、これらの定義をシフトやORと組み合わせることができます。ヘルパーマクロ(例:BIN16(B00000001,B00001010)。(32ビットはもちろんのこと、16ビットごとに個別のマクロがあるため、値は妥当ではありません。)

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


2
したがって、aのマクロがすべてある場合、CPPはファイルをどのくらいの大きさで読み取る必要がありますlong long intか?
wilhelmtell 2010

3
@wilhelmtell:そして​​、「すべての8ビットパターン」(= 256行)を指定し、それらからより多くの量を組み合わせることを提案した場合、その関連性はどうなりますか?受け入れられた回答のBOOST_BINARYでさえ、ヘッダーのすべての8ビットパターンを定義します...
Arkku

16

C ++のオーバーエンジニアリングの考え方は、ここの他の回答ですでに十分に説明されています。Cのkeep-it-simple-ffsの考え方でそれを行う私の試みは次のとおりです。

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

12

Cには、純粋な2進数のネイティブ表記はありません。ここでの最善の策は、8進数(たとえば07777)または16進数(たとえば0xfff)のいずれかです。


11

この質問にある関数を使用して、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


7

処理できる最小単位はバイト(charタイプ)です。ただし、ビットごとの演算子を使用すると、ビットを操作できます。

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

8 0進数には接頭辞が付けられ、16進数には接頭辞が付けられ0xます。10進数には接頭辞がありません。

C ++ 0xでは、ユーザー定義のリテラル使用して、希望どおりの操作を行うことができます


少なくともprintまたはcout関数で16進数のBinary値を表示できますか?
hamza

はい、できます<shameless_plug> </shameless_plug>
。stackoverflow.com/ questions / 2611764

5
一部のCコンパイラはバイナリリテラルに対して0b100101をサポートしていますが、残念ながらこれは非標準の拡張機能です。
ジョーイアダムス

3
標準では定義されていませんが、一部のコンパイラ(特にマイクロコントローラや組み込みシステム用のコンパイラ)0b00101010では、便宜上、バイナリの構文をフォームに追加しています。SDCCもその1つです。他にもSDCCを使用できるものがあると思います。(編集:ああ、私を打ち負かして、@ Joey!)
マットB.

5

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

int i;

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

std::cout << i;

OK、やややり過ぎかもしれませんが、動作します。


3
あなたのソリューションはマルチプラットフォームではありません。多くのアーキテクチャでは、アセンブリコードをCに含めることはできません。具体的には、Microsoft Visual Studioコンパイラでは(x86 32ビット用にコンパイルした場合)できます。しかし、プロセッサに「eax」レジスタがあるかどうかをどうやって知るのでしょうか。携帯電話のARMプロセッサ、x64プロセッサなどを考えてみてください。「eax」はありません。MIPSプロセッサにはコマンド 'mov'さえありません
DanielHsH

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

3

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

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


2

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

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

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ニブル

私は実際には「五分の一」と「中隔」という用語についてはあまりわかりません。誰かが代替案を知っている場合はお知らせください。

書き換えられたマクロは次のとおりです。

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

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

この例では、のバイナリ形式をに保存し10ましたx

8ulビットのサイズを定義するため、7ul7ビットを意味します。


-1

C ++はという名前の標準テンプレートを提供しますstd::bitset。よろしければお試しください。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.