C言語⑦(2025/06/04)

比較演算子

数値・変数などを比較する条件式を構成し、

条件が成立した場合は「真(true)」
条件が成立しなかった場合は「偽(false)」を返す。

数値としては「真:1」「偽:0」になる。
※ただし、bool型の変数に0以外を代入すると、すべて「1(真)」に変換される。

なお、C言語の内部的には
TRUE = 1
FALSE = 0
として扱われる。これを踏まえて、true*2を計算すると下記のようになる。

#include<stdio.h>
#include<Windows.h>

int main(void)
{
	printf("bool型のサイズは = %d\n", (int)sizeof(bool));
	printf("true = %d\n", true);
	printf("false = %d\n\n", false);
	printf("BOOL型のサイズは = %d\n", (int)sizeof(BOOL));
	printf("TRUE = %d\n", TRUE);
	printf("FALSE = %d\n", FALSE);

	bool bSmall = 2;
	if (bSmall == true) {
		printf("bSmall = %d\n", bSmall);
	}

	bSmall = -1;
	if (bSmall == true) {
		printf("bSmall = %d\n", bSmall);
	}

	BOOL bBig = -1;
	if (bBig == TRUE) {
		printf("bBig = %d(TRUE)\n", bBig);
	}
	else if(bBig == FALSE){
		printf("bBig = %d(FALSE)\n", bBig);

	}
	else {
		printf("bBig = %d(else)\n", bBig);
	}

	if (14) {
		printf("絶対に実行される??\n");
		printf("TRUE*2 = %d\n", TRUE * 2);
		printf("true*2= %d\n", true *2);
	}
	return 0;
}

【実行結果】

BOOL型のサイズは = 4
TRUE = 1
FALSE = 0
bSmall = 1
bSmall = 1
bBig = -1(else)
絶対に実行される??
TRUE*2 = 2
true*2= 2

種類は下記。

※条件式で == を使う必要がある場合、>=のほうが万一「値が等しい」を処理上でスキップした時も処理が走るようにできる。これは「誤動作」を防ぐための応用的考え方。

※例えばif文などでフラグをもとに実行判定を行う場合、if(flag)のような形でも記載でき、if(flag = true)などと書く必要はない。条件判定は「1の時に実行」「0の時には実行しない」なので、このような省略が可能。

条件判定の例

if(a == b){
  printf("%dと%は同じ",a,b);
}else{
    printf("%dと%dは違う",a,b);
}

そもそも等しくない場合だけを扱うときは下記。※「!=」は「等しくない」という比較演算子。

if(a != b){
  printf("%d"と%dは違う,a,b);

上記を踏まえて
【今日のコード①】

#include<stdio.h>

int main(void)
{
	int age1 = 45, age2 = 18, age3 = 46;
	int skin = 2;
	
	printf(" %d歳!でも%sは%d歳!!\n", age1,"心", age2);

	float weight = 82.2, weight2 = 75.6666;
	double cash = 10000000.4466;
	printf("そして体重は%fkg!!\n", weight);

	skin = 0.2f;
	printf("面の皮の厚さは%fcm!!\n ",skin);

	printf("結婚は%04d歳までに!…学生婚!?\n", age3);

	printf("体重はそれまでに%6.2fkgまで落として見せる!\n", weight2);
	printf("資産は%12.2f円まで増やしたい!!!\n", cash);

	int a = 0,b = 5;
	while (true) {
		printf("a=%d\n", a);
		a++;
		if (a >= 5)break;
	}
	
	while (true) {
		printf("a=%d\n",a);
		if (a++ >= 5)break;
	}
	if (a == b) {
		printf("%dと%dが同じ\n", a, b);
	}
	else {
		printf("%dと%dが違う\n", a, b);
	}
	return 0;
}

【実行結果】

 45歳!でも心は18歳!!
そして体重は82.199997kg!!
面の皮の厚さは0.000000cm!!
 結婚は0046歳までに!…学生婚!?
体重はそれまでに 75.67kgまで落として見せる!
資産は 10000000.45円まで増やしたい!!!
a=0
a=1
a=2
a=3
a=4
a=5
6と5が違う

if文について

C言語のif文は、特定の条件を満たす場合にのみコードを実行するための制御構造です。基本的な構文は以下のようになります。
【基本構造】
if(a == b){
    1)------;
    2)------;
}else{
    3)------;
    4)------;
}
5)------;

aとbが等しい、という条件式が成立している場合は
1)2)5)の順で処理される
aとbが等しい、という条件式が成立していない場合は
3)4)5)の順で処理される。

【具体例】
#include <stdio.h>

int main() {
    int num = 10;

    if (num > 5) {  // 条件式
        printf("numは5より大きいです。\n");
    }

    return 0;
}


if文のポイント:
- 条件式を()内に記述し、trueの場合に{}内のコードが実行されます。
- elseを追加すると、条件がfalseのときに別のコードを実行できます。
- else ifを使用すると、複数の条件を処理できます。
if (num > 10) {
    printf("numは10より大きいです。\n");
} else if (num == 10) {
    printf("numは10です。\n");
} else {
    printf("numは10以下です。\n");
}
(by 講師+Copilot)

bool型とBOOL型
bool型:true,false 1byte
BOOL型:TRUE,FALSE 4byte(intと同じ)。Windows専用(windows.hをincludeする必要あり)

本来なら、フラグとして使うなら1ビットあれば十分なのに、BOOL型が4バイトなのは不思議ですよね。
これはメモリアラインメント(メモリの配置最適化)と処理速度の観点が関係しています。
理由①:メモリアラインメントの影響
- 多くのCPUは、効率よくデータを処理するために特定のサイズ(通常は4バイトや8バイト)でデータを扱うように設計されています。
- メモリアクセスの効率を考えると、4バイトに揃えることでCPUの処理が速くなります。
理由②:整数型との互換性
- Windows APIでは、BOOL型はint(通常4バイト)と同じサイズにすることで、関数の引数として扱うときに型の統一がしやすくなるという利点があります。
- BOOL型がintと同じサイズなら、関数間でのデータのやり取りがスムーズになり、余計な型変換をしなくて済むのです。
理由③:プロセッサの特性
- 多くのプロセッサは 1バイトのデータを扱うより、4バイト単位で処理するほうが高速 になることがあります。
- 1バイトのデータを使う場合、余分なオーバーヘッドが発生することがあり、逆に処理が遅くなることもあります。

C言語標準の _Bool との違い
一方で、C99以降では標準の_bool型が導入され、こちらは 1バイト になっています。
標準Cの _bool 型は、余計なメモリを使わないことを重視した設計になっているため、最小限のメモリ使用を優先しています。

まとめ
「所詮フラグなのに…」という気持ちはよく分かりますが、処理速度、メモリアラインメント、型の互換性のためにBOOL型が4バイトになっているんですね!
プログラミング言語の設計には、単に「メモリの節約」だけでなく、「CPUの効率的な動作」や「APIとの整合性」も考慮されているわけです。😃
少し納得できましたか?🤔

上記を踏まえて【今日のコード②】

#include<stdio.h>
#include<Windows.h>

int main(void)
{
	printf("bool型のサイズは = %d\n", (int)sizeof(bool));
	printf("true = %d\n", true);
	printf("false = %d\n\n", false);
	printf("BOOL型のサイズは = %d\n", (int)sizeof(BOOL));
	printf("TRUE = %d\n", TRUE);
	printf("FALSE = %d\n", FALSE);

	
	bool bSmall = 2;
	if (bSmall == true) {
		printf("bSmall = %d\n", bSmall);
	}

	bSmall = -1;
	if (bSmall == true) {
		printf("bSmall = %d\n", bSmall);
	}

	BOOL bBig = -1;
	if (bBig == TRUE) {
		printf("bBig = %d(TRUE)\n", bBig);
	}
	else if(bBig == FALSE){
		printf("bBig = %d(FALSE)\n", bBig);

	}
	else {
		printf("bBig = %d(else)\n", bBig);
	}

	return 0;
}

【実行結果】

bool型のサイズは = 1
true = 1
false = 0

BOOL型のサイズは = 4
TRUE = 1
FALSE = 0
bSmall = 1
bSmall = 1
bBig = -1(else)

BOOL型は、数値がそのまま格納され、0,1以外だとTRUEともFALSEとも判断されない。
ただし、if文等の条件式は「0以外は真」と扱われるためif(bBig)等と記述すれば動作はする。

ブール代数とbool型

ブール代数とbool型の関係は、論理的な真偽値の処理にあります!簡単に言うと、**ブール代数は「論理演算の数学的なルール」**を定めたもので、bool型はそのルールをプログラムで使えるようにしたものです。

① ブール代数とは?
ブール代数は、数学者 ジョージ・ブール によって考案された論理演算の仕組みです。
普通の代数(xやyを使った計算)と違い、「真(1)」と「偽(0)」の2つの値だけを扱うのが特徴です。
基本的な演算: | 演算 | 記号 | 説明 | |------|------|------| | AND(論理積) | A ∧ B または A && B | 両方が1なら結果も1 | | OR(論理和) | A ∨ B または A || B | どちらかが1なら結果も1 | | NOT(否定) | ¬A または !A | 1なら0、0なら1 |
例えば、
- 1 AND 0 = 0(両方が1じゃないので結果は0)
- 1 OR 0 = 1(どちらかが1なので結果は1)
- NOT 1 = 0(1の反対だから0)

② bool型との関連
C言語などのプログラミングでは、bool型(またはBOOL型)を使ってブール代数の論理演算をプログラムで実装できます。
#include <stdio.h>
#include <stdbool.h>

int main() {
    bool a = true;  // a = 1
    bool b = false; // b = 0

    printf("AND: %d\n", a && b); // 1 AND 0 → 0
    printf("OR: %d\n", a || b);  // 1 OR 0 → 1
    printf("NOT a: %d\n", !a);   // NOT 1 → 0

    return 0;
}


このコードは、ブール代数の基本的な演算をbool型を使って再現している例です。

③ ブール代数は論理回路でも活躍!
実は、ブール代数は**コンピュータのハードウェア(論理回路)**の設計にも使われています。
CPUの中では、「ANDゲート」「ORゲート」「NOTゲート」といった論理回路が、ブール代数のルールを使ってデータを処理しているんです!💡

まとめ
✅ ブール代数は 論理演算の数学的ルール
✅ bool型は ブール代数の考え方をプログラムで使うための型
✅ &&, ||, ! で ブール代数の演算をコードで表現できる
✅ コンピュータの回路設計にもブール代数が活用されている
論理的な処理を理解すると、プログラミングもより楽しくなりますよ!😃✨
(by Copilot)

※キャスト(型変換)について

(int)sizeof(bool) の部分は 型変換(キャスト) の仕組みを使って、sizeof(bool) の結果を int 型に変換する処理です。
① sizeof(bool) の役割
sizeof(bool) は、bool型が何バイトのサイズを持っているか を取得する演算子です。
例えば、以下のコードで sizeof(bool) の結果を確認できます。
#include <stdio.h>
#include <stdbool.h>

int main() {
    printf("bool型のサイズは = %zu バイト\n", sizeof(bool)); 
    return 0;
}


このコードを実行すると、1バイト と表示されるはずです(通常_Bool型は1バイト)。

② (int) の意味
(int)sizeof(bool) の (int) は キャスト(型変換) を意味します。
sizeof(bool) の結果は size_t 型(サイズを表す型)ですが、
size_t は通常 unsigned の型であるため、int に変換して扱いやすくしています。

③ printf との関係
printf の書式指定 %d は int型専用 です。
しかし sizeof(bool) の結果は size_t 型なので、そのままだと %d では適切に表示できません。
そこで、(int) をつけることで size_t を int に変換 し、printf で正しく表示できるようにしています。

④ もっと適切な方法
最近の C 言語では、size_t 型の値を表示する場合は %zu を使うのが推奨されています。
そのため、型変換せずに %zu を使う方が望ましい です。
#include <stdio.h>
#include <stdbool.h>

int main() {
    printf("bool型のサイズは = %zu バイト\n", sizeof(bool)); 
    return 0;
}


このようにすれば キャストなしで適切に出力 できます!✨

⑤ まとめ
✅ sizeof(bool) は bool型のサイズを取得
✅ size_t 型は通常 unsigned 型なので、int に変換すると扱いやすい
✅ printf("%d", (int)sizeof(bool)) は size_t を int に変換して表示
✅ 最近は %zu を使うのが推奨される
キャスト (int) をする理由は「size_t のままだと %d に適さないから」 ということですね!😃
(by Copilot)

※直値

「直値」とは?
「直値(リテラル)」とは、ソースコード内で直接記述される値のことを指します。たとえば、次のようなものが「直値」です。
int x = 20;  // ここで「20」は直値(リテラル)
float y = 3.14;  // ここで「3.14」は直値(リテラル)
char c = 'A';  // ここで「'A'」は直値(リテラル)

つまり、「直値」は「変数に代入できる数値(または文字など)の具体的な値」であり、必ずしも「代入すること」に限定されるわけではありません。
例えば、以下のようにprintfで直接使用する場合も「直値」です。
printf("数値は %d です\n", 20);  // ここで「20」は直値(リテラル)

誤解されやすいポイント
📌 「直値 = 直接代入」ではない!
「直値」は単なる具体的な値なので、必ずしも「代入すること」だけを意味するわけではありません。
実際、代入せずに使用するケース(関数の引数や演算)もあります。
📌 変数は「直値」ではない!
たとえば int x = 20; では、x は変数であり、「直値」ではありません。
「20」は直値ですが、x は「記憶領域を持つ変数」なので直値とは区別されます。

より適切な説明
「直値とは、ソースコード内で直接記述される具体的な値のこと。例えば 20 や 3.14 などの数値、'A' のような文字も含まれる。」と説明すると、より正確になります!😃
💡 「直値を代入できる」 という説明は間違いではありませんが、「直値は代入以外にも使われる」 という視点を持つと、より理解が深まりますね!✨
(by Copilot)

コメント

タイトルとURLをコピーしました