論理演算について
[Japanese Pocket C User's Page]-[Tips!]
PocketCプログラムをする上で、論理演算について知っていないと対応できない場合があります。
特にシステムが返す値が、複数のパラメータの論理和であったりする場合は、
論理演算を駆使しないとどのような状態なのか判断ができません。
そこで、ここでは簡単ですが論理演算に関する考え方と、PocketCでの利用例について述べます。
1.2進数について
コンピュータの内部では、数字は2進数で記憶されています。
私たちが普段利用しているのは10進数です。
2進数は0と1だけで数字をあらわします。
例として、0から15までを2進数であらわすと、次のようになります。
10進数 | 2進数 |
0 | 0 |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
11 | 1011 |
12 | 1100 |
13 | 1101 |
14 | 1110 |
15 | 1111 |
2進数の1桁目が1の位、2桁目が2の位、
3桁目が4位すなわち2の2乗の位、4桁目が8の位すなわち2の4乗の位となっています。
つまりN桁目が2の(N-1)乗の位となっています。
2.論理演算
論理演算とは本来は集合に対する演算です。数学の本ではないので、
集合についての記述はしません。ここでは、論理式とその演算結果について
記述します。また、論理演算は基本的に桁の繰り上がり、下がりは発生しませんので、
2進数の各桁同士で計算した結果がその桁の値になります。
また、論理式の場合、その値を真(True)や偽(false)と呼ぶことがあります。
真は数字の1、偽は数字の0で現します。
1) or (論理和)・・・どちらか一方に存在すれば真。演算子は "|
A |
B |
A | B |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
2)and(論理積)・・・両方に存在すれば真。演算子は"&"
A |
B |
A & B |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
3)xor(排他的論理和)・・・どちらかにのみ存在すれば真。演算子は"^"
A |
B |
A ^ B |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
3.プログラムへの応用
論理演算をプログラムに応用するときは、次の点に注意してください。
1)演算対象は整数型
演算の対象になるのは整数型です。そのため、10進数と2進数の変換をマスターしておくことが望ましいです。
2)引数がどのような値をとるか確認すること
プログラム上で論理演算を使う局面では、比較対象となる数値がどのような値をとるか知っておく必要があります。多くの場合はヘルプやヘッダーファイルに書かれていますので、あらかじめ確認しておきましょう。また、このときに記載されている数値は16進数0xではじまる)でかかれていることが多いので注意してください。
4.サンプルソースを見よう。
ここで、サンプルソースを見てみます。
指定されたファイルに対し、関数GetFileAttrで取得したファイルの属性を論理演算を利用して確認するという内容です。
logical.pc (plain text)
// 1) 関数logicを宣言 // 引数 i_obj 論理演算の対象 // i_chk ビット演算の確認する対象 // 戻値 1 i_objにi_chkで指定されたビットが立っている場合 // 0 ビットが立っていない場合 // 例 logicalchk(4,2)=0 100と10 // logicalchk(6,2)=1 110と10 int logicalchk(int i_obj,int i_chk) { if ((i_obj & i_chk) == i_chk) { return 1; } else { return 0; } ; } main() { string str_filename; int i_fileattrib; str_filename=OpenFileDlg("Text File|*.txt"); // 2)ファイル名の取得 if (str_filename!="") { putsl("File :"+str_filename); /* ファイルの属性を取得 */ i_fileattrib=GetFileAttr(str_filename); // 3)ファイルの属性を取得 // 4)ファイルの属性をもとに状態を確認。比較している値については、 // GetFileAtttrを参照 if (logicalchk(i_fileattrib, 0x00000001)==1) { putsl(" 読取り専用"); }; if (logicalchk(i_fileattrib,0x00000002)==1) { putsl(" 隠しファイル"); } if (logicalchk(i_fileattrib,0x00000004)==1) { putsl(" システムファイル"); } if (logicalchk(i_fileattrib,0x00000020)==1) { putsl(" アーカイブ"); } } else { // 5)ファイルの指定がキャンセルされた場合 putsl("ファイルが指定されていません"); } graph_off(); }
4.解説
1)関数logicalchkを宣言
この関数は、第1引数で与えられた整数に、
第2引数で与えた整数で示されるビットが立っているかを確認します。
このサンプルでは、この部分がミソです。
なぜ引数同士でandをとった結果を引数と比較しているのでしょうか?
第1引数において、第2引数で与えられた値のビットがすべて1かを確認するためには、
andの結果が、第2引数とまったく同じになればいいからです。
この点については、自分で2桁の2進数同士の計算の表を作って確認してみてください。
2)ファイル名を取得
関数OpenFileDlgを使ってファイル名を取得しています。
その後、ファイルが指定されれば、3)以後を、
指定されなければ、5)を実行します。
3)ファイルの属性を取得
4)ファイルの属性を判断して表示
関数GetFileAttrを使いファイルの属性を取得しています。
ファイルの属性は各属性の整数値のORをとったものとなっているため、
各属性の値が含まれているかどうかを確認するために、
先ほどのlogicalchk関数を呼び出し、その結果を表示しています。
5)ファイルの指定がキャンセルされた場合
ファイルの指定がキャンセルされた場合はその旨を表示します。
5.おさらい
ここで覚えたこと
・2進数について・・・10進数と2進数で変換出来るようになろう
・論理演算は整数に対して行う
・and,or,xorの挙動について
・関数OpenFileDlgの使い方
・関数GetFileAttrの使い方