【C++】巨大なビット配列の用意の仕方

このQ&Aのポイント
  • C++で巨大なビット配列を用意する方法について教えてください。
  • 数値計算用のプログラムで、2^16個の「on」または「off」のデータをメモリに記憶させる必要があります。どのようにビット配列を用意すれば効率的に処理できるでしょうか?
  • ビットフィールドを使用して実装しようとしましたが、基本型のビット数を超えるためにコンパイルが通りませんでした。C++で大きなビット配列を扱う方法についてアドバイスをいただけますか?
回答を見る
  • ベストアンサー

【C++】巨大なビット配列の用意の仕方

現在C++で数値計算用のプログラムを組んでいます。 その計算の中で、2^16個の「on」または「off」のデータをメモリに記憶させる必要があります。その一つ一つにわざわざintやshortなどの既存のデータ型を使うのは馬鹿らしいので、2^16桁の二進数列(=8.2KB程度)を用意して操作したいと思っています。 (もし仮にon=+1,off=0などとしてint型配列を使うと、262KB必要となり、いくつも宣言することがためらわれます。この2^16個のデータを収める「配列」は全部で8000個程度用意したいのです。) これだけ大きなビット配列を、C++で用意するにはどうしたらよいでしょうか? 試しにビットフィールドを用いて struct bit{ unsigned elm :1<<16;  //2^16個のビット数列 }; と宣言してみたのですが、基本型のビット数を超えるからとコンパイルは通りませんでした。@VC++ リソースを活用するためにビット配列を扱った経験のある方など、どうかご教授よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

std:bitset ビット操作ならね 動的に確保したいならvector使えば大丈夫

buenaarbol
質問者

お礼

下記の方々から教えていただいたvectorとbitsetで迷ったのですが、試しにbitsetで実装したところ見事思い通りの挙動をしてくれました。これで少ないリソースを有効に活用できそうです。 実装できたからという理由で申し訳ないのですが、みなさんを代表して、ベストアンサーに選ばせていただきます。ありがとうございました。

その他の回答 (3)

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

std::vector<bool>を使ってみることですね。 ビットをパックしてメモリ効率の良い実装になっているかもしれません。 確実に詰め込みたいなら自作クラスにして自分でビット操作するのが一番です。

buenaarbol
質問者

お礼

ご回答ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

もう 1つ: std::vector<bool>

buenaarbol
質問者

お礼

標準ライブラリにちゃんと欲しい機能が実装されていたのですね。教えていただきありがとうございます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

自分でビット操作するのが安全.

関連するQ&A

  • C言語のビットフィールドについて

    はじめまして,今C言語を勉強中なのですが, ビットフィールドの宣言について質問があります。 勉強に使用しているテキストでは, ビットフィールドの宣言にはunsigned int型を使用すると書かれています(下記例参照)。 ここで質問は,unsigned charなどの型は推奨されない理由があるのか,ということです。 実際にunsigned char型で実行してもプログラムは動きますし,そちらのほうが語長も短くて済むのでいいような気がします。 テキストの書き方だと,他の型について言及していなかったので,なにか理由かあるのか,それとも特に問題ないのか,疑問に思っています。 わかる方いましたら,回答いただけると嬉しいです。 (ex) struct{ unsigned int bit0:1; unsigned int bit1:1; : unsigned int bit7:1; }bits;

  • C言語で確保できるビットの桁数

    C言語でビット単位でデータ操作する際に、確保できるビットの桁数はたとえば以下のような例の場合 unsigned char bit; 1バイト(=8ビット)なので8桁ということは勉強しました。 ここで、たとえば計算でビットの桁数を100桁用意したい場合 以下のように32*4桁という風に分ける方法しかないのでしょうか? unsigned int bit[4]; できれば一つの変数で済ませたいのですが、何か良い方法をご存知の方いらっしゃいましたらよろしくお願いします。

  • C言語のビットフィールドで分からないところがありま

    union UNION { struct { unsigned int a :(32-8-5); // この部分 unsigned int b :8; unsigned int c :5; }BIT; }; 上記の「この部分」と書いてある行の意味を教えてください よろしくお願いします

  • C# 配列の変数宣言について。

    C#についての質問です。 新たなint型の配列dataを作るため変数宣言文を、以下のように書きました。 int[] data; すると、以下のような警告文が出ました。 『フィールド'IntArray.data'は割り当てられません。常に既定値nullを使用します。』 そこで調べてみたところ、「newしていないからこのような警告文が出る」ということがわかったので、以下のように書き換えました。 private int[] data = new int[]; すると今度は 『配列を作成するには、配列のサイズまたは配列の初期化子を指定する必要があります。』 というエラー文が出てしまいました。 このとき、配列のサイズも初期化子も指定したくない場合には、どのようにプログラムを書けば良いのでしょうか? お分かりになる方がいらっしゃいましたら、ご助言をお願いします。

  • c# 配列変数の宣言について

    c#の配列変数の宣言についてですが、 以下の2つの宣言は同じことなのでしょうか。 (1)int[] num = {1,2,3}; (2)int[] num = new int{1,2,3}; 本では(2)のような定義していますが何かルールのようなものがあるのでしょうか。 宜しくお願いします。

  • 配列の書き方

    C言語の配列の宣言で unsigned char aaa[256/8] という表現があるのですが、これはどういう意味でしょうか?

  • 配列、添え字に関するコンパイルエラーにつきまして。

    現在、arduinoで赤外線リモコンを作成しております。 ネット上の情報を参考にON/OFFのみの送信・受信はできたので、ボタンの数(mode)を21種類に増やして送信機を作成を試みております。 赤外線のON/OFFパターンの配列データが大きかったのでdata[][67]としてPROGMEM に保管し、SRAMにondata[67]として読み込もうとしています。 この状態でコンパイルすると下記のようなエラーが出てしまいます。 [mode][i][cnt]を配列のインデックス(添え字)として使っていますが、これを使用している行にこのエラーが出ます。 調べてみると添え字はintではいけないといった情報もみかけますが、data[i]のように使用されているのをよく見かけます。 データ型を変えてみたり試してみたのですが、'char[int]' や'int[char]'のように変わるだけで解決しませんでした。 このエラーに対して何か解決策があればご教授願えないでしょうか。 よろしくお願い致します。 ※エラー invalid types 'int[int]' for array subscript ※グローバル変数(PROGMEM に保存) const uint16_t data[21][67] PROGMEM = { /* 4bytes(16bits), Leader code & Customer code(CC) & Data code & ^Data code & Mode code */ /* data[0] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600}, /* data[1] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600},           ・           ・           ・ /* data[20] */ {9200, 4500, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 1650, 600, 1650, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600, 550, 600, 1650, 600}, }; ※関数 void sendOnSignal(int mode){ int ondata[67]; for (int i = 0; i < 67; i++) {ondata[i] = pgm_read_word_near(&(data[mode][i]));} int dataSize = sizeof(ondata[mode]) / sizeof(ondata[mode][0]); /* IRcodeの配列数を計算。67になるはず。 */ for(int cnt = 0; cnt < 67; cnt++) /* iIndexIRcode(現在の配列)が偶数番目ならhigh。 奇数番目ならlow。 */ { unsigned long len = ondata[mode][cnt]; /* lenに現在の配列の時間を代入。 */ unsigned long us = micros(); /* usにパルス開始時刻を記録。 */ do { /* 周波数38kHzでOn/Offするように配列の時間分点滅。 */ digitalWrite(IRLED_pin, (cnt%2) ? LOW : HIGH); /* 三項演算子[A ? B : C] (Aがtrueの場合はB,falseの場合はCを実行する) */ delayMicroseconds(8); /* キャリア周波数38kHzでON/OFFするよう時間調整 */ digitalWrite(IRLED_pin, LOW); delayMicroseconds(7); } while (long(us + len - micros()) > 0); /* 送信時間に達するまでループ */ } } /* void sendSignal終了*/

  • 配列の確保の仕方

    C言語でプログラムを記述していますが、 確保している配列が多すぎるためか、 access vilation at ・・・ などのエラーが出ます。 <プログラム> #define A 1000 #define B 10000 をグローバルで宣言して、各関数内でこれを用いて宣言しています。 int data[A][B]; double root[A][B];   ・   ・   ・ int score[A][A][B]; などを初めにたくさん宣言しています。 聞くところによると、動的に確保すればいい、とも聞いたんですが、あまり意味がわかりません。 上のエラーメッセージが出ないようにするにはどうすればいいのでしょうか? この説明だけでお分かりいただけないなら、言っていただければ詳しく言います。

  • C言語の配列の扱い

    次のような配列bufと変数dataを宣言して bufの中身をdataにコピーしたいのですが、 buf[0]のみで、buf[1]の値が入りません。 具体的には、buf[0]には16進数で0x3f、 buf[1]には0x3aが入っていて、 dataの値を0x3a3fにしたいのです。 教えてください。 ***************************** unsigned char buf[2]; unsigned short data; data = (unsigned short)*buf; *****************************

  • C言語のfwrite関数について

    現在,バイナリのデータを処理するプログラムを作成しています。 おおまかに言えば,ファイルA(バイナリモードでオープン)からバイナリでデータを読み込んできて,そのデータを処理してファイルB(バイナリモードでオープン)に書出す,のようなプログラムです。 その処理したデータを入れるデータ型にunsigned long long int型(64bit)を使用しています。 その処理データをファイルBに書出す時に,fwrite関数を用いています(例参照)。 (例) for(i=0; i<N; i++){ fwrite(&c[i], sizeof(c[i]), 1, fp); } //配列cが「unsigned long long int型」です。 //配列cは最初に"0"で初期化しています。 //fpはファイルポインタです。 しかし,本システムでunsigned long long int型が実際に使用しているのは下位32bitです。 上の例で書出した場合,上位32bitの"0"も書出されていることになるのでしょうか。 書出されたファイルのサイズを見れば,64bit全て書出されているようですが,計算間違いで32bitを超えたところまで何かデータが入っている可能性もあります。 どなたはfwrite関数に詳しい方,ご回答をよろしくお願いします。