画像(logo)

HOME/[C言語 入門]小学生でもわかるC言語3 目次/最終日 論理演算

広告

[C言語 入門 小学生でもわかるC言語3]
最終日 論理演算

広告

↓2016年02月29日発売↓

12歳からはじめる ゼロからのC言語 ゲームプログラミング教室

目次へ戻る

論理演算

最終日の今回は論理演算についてやっていきたいと思います。

実際の使い方だけ紹介いたしますのでもし2進数の事や論理演算そのものの事がわからない場合はわからなそうな用語集の進数、符号、論理演算などの項目を見てみてください。

けっこう難しい内容なども含まれるわりには、プログラムの種類によっては全く使う事もないような内容なのでもしここで理解不能でも、必要に応じて再び学べば良いかと思われますので気楽にいって頂ければと思います。

いちよう「char」型は1バイト、「int」型は4バイトとして話を進めさせて頂きます。

OR

「OR」は「|」を使います。

/*最終日 プログラム1*/
#include <stdio.h>

int main(){
	unsigned char var = 0xff;
	unsigned char ans = 0;

	printf("11111111\nOR\n00001111\n\n");

	ans = var | 0x0f;

	printf("ans = %x\n",ans);

	return 0;
}

■実行結果■

画像(ci_14_1)

2進数8ケタの計算をしております。

変数「char」や「int」の先頭に「unsigned」をつけると符号なしになるのですが、「printf()」関数の表示バグ?みたいなものにならないようにこちらを先頭につけております。

「何を言っているのかわからない」という方は試しに上記のプログラムの先頭の「unsigned」を削除するとわかるかと思われます。

表示する時に先頭に謎の「ffffff」が付与されます。

「int」で試してもこうはならないし、今のトコロ原因はわかりませんのでご了承ください。

(計算する時の弊害はもちろん符号あり、なしを考慮した上でいずれにせよ1バイト以上の領域は切り捨てられるのであくまでも表示バグという事で問題ないようです)

話を戻しますが、16進数を使う場合は先頭に「0x」、表示する時は「%x」で表示します。

2進数そのまま表示する方法は「%d」みたいな指定方法ではできないので後ほど紹介します。

少し前置きが長引いてしまいましたが、「OR」の場合はどちらか片一方でも「1」なら1なので結果「ff」になりますね。

AND

「AND」は「&」を使います。

/*最終日 プログラム2*/
#include <stdio.h>

int main(){
	unsigned char var = 0xff;
	unsigned char ans = 0;

	printf("11111111\nand\n00001111\n\n");

	ans = var & 0x0f;

	printf("ans = %x\n",ans);

	return 0;
}

■実行結果■

画像(ci_14_2)

「AND」の場合は両方「1」の時のみ「1」なので結果「f」だけですね。

XOR

「XOR」は「^」になります。

/*最終日 プログラム3*/
#include <stdio.h>

int main(){
	unsigned char var = 0xff;
	unsigned char ans = 0;

	printf("11111111\nXOR\n00001111\n\n");

	ans = var ^ 0x0f;

	printf("ans = %x\n",ans);

	return 0;
}

■実行結果■

画像(ci_14_3)

「XOR」は両方が異なる場合に「1」ですね!

NOTと反転

「NOT」は「!」、反転は「~」チルダを使います。

/*最終日 プログラム4*/
#include <stdio.h>

void disp_binary(char );

int main(){
	unsigned char var = 0xef;

	disp_binary(var);
	var = ~var;
	disp_binary(var);

	printf("\n");

	var = 0xef;
	disp_binary(var);
	var = !var;
	disp_binary(var);

	printf("\n");

	var = 0x00;
	disp_binary(var);
	var = !var;
	disp_binary(var);

	return 0;
}

void disp_binary(char c){
	int i;
	for(i=sizeof(char) * 8 - 1;i>=0;i--){
		printf("%d",(c >> i) & 0x01);
	}
	printf("\n");
}

■実行結果■

画像(ci_14_4)

2進数を表示する関数「disp_binary()」の説明は後ほどビットシフトの項目でいたします。

「~」チルダを使うと反転されるのが確認できましたね!

ただ「NOT」には注意が必要です。

なんとなく「NOT」も「1」なら「0」、「0」なら「1」とひっくりかえるイメージなので反転しそうですが、「NOT」を使った場合は

「1以上の場合は0に」

「0の場合は1に」

なりますので注意してください。

反転したい場合他の方法として「? XOR 0xff」のように「f」で埋めた数でXORを使う方法もあります。

11110000

XOR

11111111

00001111

反転されます。

広告

文字→数字変換

たとえば論理演算を使って文字→数字の変換ができます。

/*最終日 プログラム5*/
#include <stdio.h>

int main(){
	int var1 = 49;
	int var2 = 50;
	int var3 = 51;

	printf("変換前\n");
	printf("var1 = %c\n",var1);
	printf("var2 = %c\n",var2);
	printf("var3 = %c\n",var3);

	var1 = var1 & 0x0f;
	var2 = var2 & 0x0f;
	var3 = var3 & 0x0f;

	printf("変換後\n");
	printf("var1 = %d\n",var1);
	printf("var2 = %d\n",var2);
	printf("var3 = %d\n",var3);

	return 0;
}

■実行結果■

画像(ci_14_5)

文字の数字の「1」は2進数で「00110001」

これを「0x0f」→2進数「00001111」で「&」をとるので

結果、下位の数字だけが残るというワケです。

ビットシフト

続いてビットシフトになります。

ビットシフトというのは2進数をそのまま左へ、右へずらすような行為の事をいいます。

結果左にずらした場合はその2倍の数が、右にずらした場合はその2分の1の数が得られます。

ずらして正常に値が得られる限界がありますが、そのへんの説明は省略させて頂きます。

左にずらす時は「<<」、右にずらす時は「>>」を使います。

/*最終日 プログラム6*/
#include <stdio.h>

int main(){
	unsigned char var = 12;

	printf("var = %d\n",var);
	printf("左に1ビットシフト\n");
	printf("var = %d\n",var << 1);

	printf("右に1ビットシフト\n");
	printf("var = %d\n",var >> 1);

	return 0;
}

■実行結果■

画像(ci_14_6)

「変数 << ずらすビット数」

のように使います。

2進数に変換

たとえばビットシフトを使って2進数を表示する事ができます。

/*最終日 プログラム7*/
#include <stdio.h>

int main(){
	unsigned char c = 12;
	
	printf("%d",(c >> 7) & 0x01);
	printf("%d",(c >> 6) & 0x01);
	printf("%d",(c >> 5) & 0x01);
	printf("%d",(c >> 4) & 0x01);
	printf("%d",(c >> 3) & 0x01);
	printf("%d",(c >> 2) & 0x01);
	printf("%d",(c >> 1) & 0x01);
	printf("%d",(c >> 0) & 0x01);

	printf("\n");

	return 0;
}

■実行結果■

画像(ci_14_7)

変数をフラグのように使う

今までの事を利用して普通の変数をフラグのように使うプログラムを作ってみました。

/*最終日 プログラム8*/
#include <stdio.h>

void disp_flag(unsigned char );
int get_flag(unsigned char ,int );
void set_flag(unsigned char *,int );
void reset_flag(unsigned char *,int );

int main(){
	unsigned char flag = 0;

	printf("現在のフラグ\n");
	disp_flag(flag);

	printf("\nフラグ1をセット\n");
	set_flag(&flag,1);
	disp_flag(flag);

	printf("\nフラグ5をセット\n");
	set_flag(&flag,5);
	disp_flag(flag);

	printf("\nフラグ5をリセット\n");
	reset_flag(&flag,5);
	disp_flag(flag);

	printf("\nフラグ1の状態 = %d\n",get_flag(flag,1));

	return 0;
}

void disp_flag(unsigned char flag){
	int i;
	for(i=sizeof(char) * 8 - 1;i>=0;i--){
		printf("%d",(flag >> i) & 0x01);
	}
	printf("\n");
}

int get_flag(unsigned char flag,int num){
	return (flag >> num-1) & 0x01;
}

void set_flag(unsigned char *flag,int num){
	unsigned char tmp = 1;	
	if(!(get_flag(*flag,num)==1)){
		tmp = tmp << num-1;
		*flag += tmp;
	}	
}

void reset_flag(unsigned char *flag,int num){
	unsigned char tmp = 1;	
	if(get_flag(*flag,num)==1){
		tmp = tmp << num-1;
		*flag -= tmp;
	}	
}

■実行結果■

画像(ci_14_8)

もちろん「char」型ではなく「int」型で作れば4バイトの場合32bitのフラグとして使う事ができます。

お疲れ様です!

これにて「小学生でもわかるC言語3」を終了したいと思います!

最後までお付き合いいただいた方は感謝です!

このサイトを通して少しでもプログラミングの楽しさを感じていただけたら幸いです!

□ページの先頭へ□

□目次へ戻る□

□HOME□

広告

↓2017年06月16日発売↓

やさしいC 第5版 (「やさしい」シリーズ)

新品価格
¥2,700から
(2017/5/1 13:05時点)

↓2014年08月09日発売↓

新・明解C言語 入門編 (明解シリーズ)

新品価格
¥2,484から
(2017/5/1 13:08時点)

↓2016年02月20日発売↓

新・解きながら学ぶC言語

新品価格
¥2,160から
(2017/5/1 13:10時点)

↓2017年02月11日発売↓

C言語プログラミング基本例題88 88

新品価格
¥3,024から
(2017/5/1 13:12時点)

↓2016年12月15日発売↓

Cの絵本 第2版 C言語が好きになる新しい9つの扉

新品価格
¥1,490から
(2017/5/1 13:13時点)

↓2017年02月08日発売↓

新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ)

新品価格
¥2,700から
(2017/5/1 13:15時点)