変数とデータ型

変数はラベルの付いた箱のようなものです——箱には名前と型があり、正しい種類のものしか入れられません。違うものを入れるとトラブルになります。

変数とは

変数はプログラム内でデータを格納するための名前付きメモリ位置です。箱に例えると:

変数の宣言と初期化

変数の宣言

変数を宣言するとコンパイラに「箱が必要です。名前と型はこれです」と伝えます:

C
int age;
float weight;
char blood_type;

宣言直後、変数の値は未定義(ゴミ値)です——そのメモリ位置に残っていたランダムなデータが入っています。未初期化の変数は絶対に使わないでください!

変数の初期化

初期化とは、宣言と同時に変数に初期値を与えることです:

C
int age = 20;
float weight = 65.5f;
char blood_type = 'A';
💡 ヒント: 変数は宣言時に必ず初期化しましょう。これは良い習慣であり、未定義値による追跡困難なバグを防げます。

先に宣言、後で代入

宣言してから後で代入することもできます:

C
int age;
age = 20;

結果は同じですが、2 段階に分けると宣言と代入の間で未初期化のまま変数を誤って使ってしまうリスクが高まります。

同じ型の変数をまとめて宣言

C
int a = 1, b = 2, c = 3;
⚠️ 注意: 1 行で複数の変数を宣言・初期化すると可読性が下がります。それぞれに意味のある初期値があるなら、別々の行に書きましょう。

変数の命名規則

C言語には変数名に関する厳格な規則があります:

守らなければならないこと:

守るべきこと:

名前 有効? 備考
age 有効 短くて意味が明確
_count 有効 アンダースコアで始まる
student_name 有効 snake_case スタイル
2nd_place 無効 数字で始まる
my-score 無効 ハイフンを含む(減算と解釈される)
int 無効 キーワード
Age 有効だが非推奨 先頭大文字は通常型名に予約

基本データ型

C言語のデータ型は、変数が占めるメモリ量、値の範囲、データの解釈方法を決定します。C99 の基本データ型は次の通りです:

整数型

サイズ(バイト) 代表的な範囲 フォーマット指定子
char 1 -128 ~ 127 %c または %d
unsigned char 1 0 ~ 255 %u
short 2 -32768 ~ 32767 %hd
unsigned short 2 0 ~ 65535 %hu
int 4 -2147483648 ~ 2147483647 %d
unsigned int 4 0 ~ 4294967295 %u
long 4 または 8 プラットフォーム依存 %ld
unsigned long 4 または 8 プラットフォーム依存 %lu
long long 8 -9223372036854775808 ~ 9223372036854775807 %lld
💡 ヒント: 日常的なプログラミングでは int で十分です。より大きな範囲が必要なときは long long を、文字には char を使いましょう。最近のプラットフォームでは intshort と同じくらい効率的なため、short はあまり使われません。

⚠️ 注意: 上の表では int が 4 バイトとしていますが、これは最近のプラットフォームでの話です。C言語の規格は int を最低 2 バイトとしか要求していません。実際のサイズはプラットフォームに依存します——sizeof で確認してください。

浮動小数点型

サイズ(バイト) 有効桁数 絶対値の範囲 フォーマット指定子
float 4 6-7 1.2e-38 ~ 3.4e38 %f
double 8 15-16 2.2e-308 ~ 1.8e308 %lf
long double 8 以上 18+ プラットフォーム依存 %Lf

浮動小数点数は精度が限られており、すべての小数を正確に表せるわけではありません。例えば:

C
float f = 0.1f;
printf("%.20f\n", f);
TEXT
0.10000000149011611938

0.1 は 2 進数で無限に循環する小数のため、float では正確に格納できません。これは浮動小数点表現の本質的な特性であり、バグではありません。

🔥 よくある間違い: 小数を扱うときはデフォルトで double を使いましょう。精度が高く、最近の CPU では float と同じ速度です。メモリに制約がある組み込みシステムでのみ float を優先してください。

文字型

char 型は本質的に 1 バイトの整数で、通常は文字の格納に使います。文字はメモリ上では ASCII コードとして格納されます:

C
char ch = 'A';
printf("%c\n", ch);
printf("%d\n", ch);
TEXT
A
65

'A' の ASCII コードは 65 です。%c で文字として出力し、%d で整数値として出力します。これは C言語では文字と整数が相互に変換可能であることを示しています。

⚠️ 注意: 'A' は文字(単一引用符)、"A" は文字列(二重引用符、末尾に \0 が付く)です。これらは全く異なるもの——絶対に混同しないでください。

_Bool型

C99 では _Bool 型が導入され、0 と 1 のみ格納できます。<stdbool.h> をインクルードすると booltruefalse が使えます:

C
#include <stdbool.h>

bool is_valid = true;
bool is_empty = false;

sizeof演算子

sizeof は C言語のキーワード(関数ではない)で、データ型や変数が占めるバイト数を返します:

C
#include <stdio.h>

int main(void) {
    printf("char:   %zu bytes\n", sizeof(char));
    printf("short:  %zu bytes\n", sizeof(short));
    printf("int:    %zu bytes\n", sizeof(int));
    printf("long:   %zu bytes\n", sizeof(long));
    printf("long long: %zu bytes\n", sizeof(long long));
    printf("float:  %zu bytes\n", sizeof(float));
    printf("double: %zu bytes\n", sizeof(double));
    return 0;
}
▶ 試してみよう
TEXT
char:   1 bytes
short:  2 bytes
int:    4 bytes
long:   4 bytes
long long: 8 bytes
float:  4 bytes
double: 8 bytes
💡 ヒント: sizeofsize_t 型を返し、そのフォーマット指定子は %zu です。コンパイラが %zu をサポートしていない場合(古いバージョンなど)は、代わりに %lu を使ってください。

sizeof は変数にも使えます:

C
int age = 20;
printf("%zu\n", sizeof(age));

フォーマット出力の詳細

整数のフォーマット

C
int n = 42;
printf("10 進数: %d\n", n);
printf("8 進数: %o\n", n);
printf("16 進数(小文字): %x\n", n);
printf("16 進数(大文字): %X\n", n);
printf("8 進数(プレフィクス付き): %#o\n", n);
printf("16 進数(プレフィクス付き): %#x\n", n);
TEXT
10 進数: 42
8 進数: 52
16 進数(小文字): 2a
16 進数(大文字): 2A
8 進数(プレフィクス付き): 052
16 進数(プレフィクス付き): 0x2a

浮動小数点のフォーマット

C
double pi = 3.141592653589793;
printf("デフォルト: %f\n", pi);
printf("小数点以下 2 桁: %.2f\n", pi);
printf("小数点以下 8 桁: %.8f\n", pi);
printf("科学的記数法: %e\n", pi);
printf("幅 12.2f: [%12.2f]\n", pi);
TEXT
デフォルト: 3.141593
小数点以下 2 桁: 3.14
小数点以下 8 桁: 3.14159265
科学的記数法: 3.141593e+00
幅 12.2f: [       3.14]

型の値の範囲

C言語の標準ライブラリには、各型の範囲を問い合わせるためのヘッダファイルが用意されています:

limits.h(整数型)

C
#include <limits.h>

printf("int の最小値: %d\n", INT_MIN);
printf("int の最大値: %d\n", INT_MAX);
printf("char の最大値: %d\n", CHAR_MAX);

よく使うマクロ:

マクロ 意味
INT_MIN int の最小値
INT_MAX int の最大値
CHAR_MIN char の最小値
CHAR_MAX char の最大値
LONG_MAX long の最大値
LLONG_MAX long long の最大値

float.h(浮動小数点型)

C
#include <float.h>

printf("float の有効桁数: %d\n", FLT_DIG);
printf("double の有効桁数: %d\n", DBL_DIG);
printf("float の最大値: %e\n", FLT_MAX);

C
#include <stdio.h>
#include <limits.h>
#include <float.h>

int main(void) {
    char ch = 'Z';
    int num = 100;
    float f = 3.14f;
    double d = 2.718281828;

    printf("char '%c' = ASCII %d, サイズ = %zu\n", ch, ch, sizeof(ch));
    printf("int %d, サイズ = %zu, 範囲 = [%d, %d]\n", num, sizeof(num), INT_MIN, INT_MAX);
    printf("float %.6f, サイズ = %zu, 桁数 = %d\n", f, sizeof(f), FLT_DIG);
    printf("double %.9f, サイズ = %zu, 桁数 = %d\n", d, sizeof(d), DBL_DIG);

    return 0;
}
▶ 試してみよう
TEXT
char 'Z' = ASCII 90, サイズ = 1
int 100, サイズ = 4, 範囲 = [-2147483648, 2147483647]
float 3.140000, サイズ = 4, 桁数 = 6
double 2.718281828, サイズ = 8, 桁数 = 15

C
#include <stdio.h>

int main(void) {
    char lower = 'a';
    char upper = lower - 32;

    printf("小文字: %c(ASCII %d)\n", lower, lower);
    printf("大文字: %c(ASCII %d)\n", upper, upper);

    printf("\n数字文字:\n");
    char digit = '0';
    printf("文字 '%c' の ASCII コード = %d\n", digit, digit);
    printf("文字 '%c' の数値 = %d\n", digit, digit - '0');

    return 0;
}
▶ 試してみよう
TEXT
小文字: a(ASCII 97)
大文字: A(ASCII 65)

数字文字:
文字 '0' の ASCII コード = 48
文字 '0' の数値 = 0
💡 ヒント: 大文字と小文字の ASCII コードは 32 離れています。小文字から 32 を引けば大文字になり、逆に 32 を足せば小文字になります。数字文字から '0' を引けばその数値が得られます——これが文字を数値に変換する基礎です。

❓ よくある質問

Q int と long long の違いは何ですか?いつ long long を使うべきですか?
A int は通常 4 バイトで最大約 21 億、long long は 8 バイトで最大約 922 京です。int の範囲では足りない場合(階乗の計算、多倍長演算など)に long long を使います。日常的なプログラミングでは int で十分です——むやみに long long を使うとメモリを無駄にし、一部のプラットフォームでは遅くなります。
Q float と double はどちらを選ぶべきですか?
A デフォルトは double です。double は 15-16 桁の有効桁数に対し float は 6-7 桁——精度の差は大きいです。最近の CPU では double の演算速度は float と変わりません。メモリに制約がある組み込みデバイスでのみ float を優先してください。
Q char は signed ですか、unsigned ですか?
A コンパイラとプラットフォームに依存します。C言語の規格は char が signed かどうかを規定していません——コンパイラが決定します。符号を保証したい場合は、明示的に signed char または unsigned char を使ってください。ASCII 文字(0-127)ならどちらでも問題ありません。127 を超える値を扱う場合は明示的に指定する必要があります。
Q なぜ未初期化の変数を使ってはいけないのですか?
A 未初期化のローカル変数はスタックに格納され、メモリに残っていたランダムなデータ(ゴミ値)を含んでいます。使用すると未定義動作になり——実行するたびに結果が変わったり、クラッシュしたりする可能性があります。この種のバグは非常に追跡が困難なので、常に宣言時に変数を初期化してください。

📖 まとめ

📝 練習問題

  1. sizeof を使って、自分のパソコンですべての整数型と浮動小数点型のバイトサイズを出力するプログラムを書いてください。同級生の結果と比較して一致するか確認しましょう
  2. 文字 'a' ~ 'z' の ASCII コードを出力するプログラムを書いてください。1 行に 5 つずつ、%-5d で整列させること
  3. INT_MAX + 1 の結果(整数オーバーフロー)を計算して出力し、INT_MIN と比較してなぜそうなるか考察してください
100%