• ベストアンサー

ビット演算を学びたい

a &= 2; a |= 2; a ^= 2; a ~= 2; a <<=2; a >>=2; みたいな感じでビット演算が使われているソースを 良く見るのですが、いまいちビット演算で何をしているのかが 分かりません。 参考書などには文字通りビットをいじるような旨のことが書いてあります。 (こちらにも同じようなことが http://www9.plala.or.jp/sgwr-t/c/sec14.html) こういうので何となくは分かるのですが、 実際にこれを何に使えるか、実践ではどのように使うのかが なかなか見えてきません。 このビット演算を私のような者でも実際のプログラムで使いこなせるように なれるようなサイトや書籍の提示、あるいはサンプルのプログラムなどで ご指導いただけたらと思います。

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

>実際にこれを何に使えるか、実践ではどのように使うのかが >なかなか見えてきません。 実際に、ビット演算が必要な状況はあまり発生しません。従って、なかなか、見えてこないのは、当然のことです。 ビット演算が必要な状況の例として、メモリのサイズを節約する場合に必要となることがあります。 では、どのような場合に、メモリを節約するかというと、 ファームウェアの場合のように、メモリの絶対量が少ない場合等があります。通常のパソコンでは、あまり、メモリの節約を意識せずにプログラミングができるので、このようなケースはあまりありません。 強いて例をあげれば、データが大量にあるとき、例えば100万件のデータがあるとき、1つのデータのサイズを小さくすると、非常に大きな効果が得られる場合があります。 もし、1つのデータが、100バイトの場合、100万件なら、10000万バイトになります。これが、半分ですむなら、5000万バイトになり、5000万バイトのメモリの節約となります。 では、どうやって、1つのデータを半分にするか(半分にはならなくても出来るだけちいさくするか)ですが、基本的には、その情報が、格納できるだけの、ビットに、縮めてしまう方法をとります。 例えばint型(4バイト)のデータは約10桁の数値が格納出来ますが、このデータのとりうる値が4桁までしか発生しないことが、明白であればshort型でとります。これにより4バイトが2バイトになります。これは、ビット演算を必要としません。 では、以下の場合は、どうでしょうか。 3種類のデータがあり、1つは性別(0:男、1:女)を表し、 もう1つは、血液型(0から3の数値があれば良い、A,B,AB,O) もう1つは、体重(0~31迄しかないとします。例ですので、それじゃ足りないというつっこみはしないで下さい) そうすると、メモリの節約をする必要がない場合は、全てinit型で確保するので4×3は12バイトになります。多少、節約の努力をすると、全てchar型でも良いので1バイト×3=3バイトになります。 これを更に、節約すると、性別:1ビット、血液型:2ビット、体重:5ビットですみます。これは、合計8ビットですので、char型(1バイト)で済みます。 そうすると、このデータが100万件ある場合は、非常に有効な節約になります。 では、性別 char sei; 血液型 char blood;体重 char weight;が与えられたとき、これを1つのchar型データ char data;にまとめるサンプルです。sei=0~1,blood=0~3,weight=0~31の数値です。 dataの左側の1ビットに、性別、次の2ビットに血液型、最後の5ビットに体重を格納します。 sei = sei << 7; blood = blood << 5; data = sei | blood | weight; 次がchar dataが与えられたときに、これを 3つの性別、血液型、体重に分解する例です。 sei = (data >> 7) & 0x01; blood = (data >> 5) & 0x03; weight = data & 0x1f;

amazontester
質問者

お礼

かなり具体的な例を挙げてくださりありがとうございます。 結構イメージが分かってきた気がします。

その他の回答 (4)

  • caceres
  • ベストアンサー率43% (61/140)
回答No.5

No1です。 No3の方の書かれたことをよくというか必ず使います。 マイコンの場合は使用メモリ量を気にしながらになりますから データ範囲が数ビット分で済む場合など、構造体として定義するとint定義で複数のメンバーを定義出来ます。 もっとも構造体を利用すればNo3の方のようなビット処理は不要です。が場合によっては高速処理になるので共用体定義にしてbit処理を利用します。 マイコンでロボット制御など1クロックでも無駄にしたくない場合はアセンブラコードを見てクロック数計算が必要になる場合もあります。 PICの無償開発ツールMplab ideと無償Cコンパイラを使って変数をWatchしながらデバッガでステップ実行するとよく分かりますよ。 以下の例ではdsPICで2サイクル構造体処理の方が早かったですがdsPICはC言語に適合する構成のためでしょう。通常はbit処理の方が早かったりわかりやすい処理も多いと思います。 //構造体 struct zData{     unsigned  sex  :1;  //性別   [0 or 1] (0=男,1=女) ****|****|****|***0     unsigned  blood:2; //血液型 [0--3](A,B,AB,O)        ****|****|****|*00*     unsigned  rh :1;   //RH     [0 or 1] (+/-)    ****|****|****|0***     unsigned  weight:10;//0~512kg Kg単位(小錦サイズも含む)   **00|0000|0000|****     unsigned  dmy:2; //16bit中 余った分 }; //共用体 union uData{  int  iDB;  struct zData zDB; }; union uData rDat; //データ格納 2byte rDat.zDB.sex=1; //女 rDat.zDB.blood=2; //AB rDat.zDB.rh=1; //RH+ rDat.zDB.weight=75; /75kg //同様にbitで書き込む場合の記述は rDat.iDB =0; rDat.iDB |=1; rDat.iDB |=(2<<1); rDat.iDB |=(1<<3); rDat.iDB |=(75<<4);

amazontester
質問者

お礼

これは確かビットフィールドとかいう手法ですね。 (独習Cで読んだ覚えが) ビットの図までつけて頂いた様で、この例もとても勉強になりました。

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.4

http://oshiete1.goo.ne.jp/qa2041537.html 演算子「 | 」について http://oshiete1.goo.ne.jp/qa2274746.html ビットシフトってどんな時使うの?

amazontester
質問者

お礼

リンク先を拝見いたしました。 とても勉強になりました。ありがとうございます。

  • herbest
  • ベストアンサー率42% (15/35)
回答No.2

メール送受信で利用されるBASE64エンコーダ/デコーダなどで使ったりします。 それほど難しくもないので実際に作って見てはどうでしょう。勉強になりますよ。 他には暗号などでもよく(ほぼ?)使います。 確かに使わないときはあんまり使わないんですよね。 勉強したいなら、例えばunsigned int型の変数を2進数で表示する関数なんか作って見てはどうでしょう。 ほんの数行の関数ですがしっかり理解してないと難しいかもしれません。

参考URL:
http://dolphin.c.u-tokyo.ac.jp/~naka7/base64.html
amazontester
質問者

お礼

なるほど。。暗号化ですか。 2進数で表示する関数をちょっと調べてみましたが、 簡単そうでなかなか複雑で勉強になりました。 ありがとうございます。

  • caceres
  • ベストアンサー率43% (61/140)
回答No.1

何に使うかはプログラムの設計をするうちに必要なことが分かってくるでしょう。 例えば シフト  4倍にするのに4を掛ければよいですがかけ算が出来ないCPUもあります。 左シフトを2回 a = a<<2; すればX4と同じです。 マイコンでロボットなどを制御する場合、乗算処理とシフト処理では 処理時間が数倍~数十倍以上違いますから乗算など使えない場合もあります。 例えば and ビット C言語ではIntのビット幅が8,16,32とCPUとコンパイラによって変わります。例えばボタンが複数あるゲームコントローラを処理する場合ですが、このようなCPUに対する入力は通常,8bit単位で処理できるものが一般的です。 つまりあるボタンひとつが1bitに相当するのでONを判定するために if(A & 1)==0{}else{} でbit0のON/OFF状態が分かります。 同様にbit1の発光ダイオード(LED)を点灯させるために B=B | 0x02; とすると **** **1* になり状態を変えることが出来ます。 コンピュータの根の深い部分の操作になると、ハードウェア処理に関する部分なので必ずビット処理が多くなります。

amazontester
質問者

お礼

実際のプロの方のようでとても参考になりました。 ゲームのコントローラーの処理などには確かに使ってそうですね。