第4章:データを扱う
この章で学ぶこと
- 変数とは何か
- 基本的なデータ型(int, char, float, double)
- 変数の宣言と初期化
- 基本的な演算
- printfによる値の表示
- 定数とマクロ
- 引き出しに名前を付ける(変数の名前)
- 引き出しの大きさを決める(データ型)
- 引き出しに物を入れる(値の代入)
- 引き出しから物を取り出す(値の参照)
---
4.1 変数とは
データを入れる箱
変数(Variable)は、データを保存するための「箱」です。
日常生活で例えると、変数は「ラベルの付いた引き出し」のようなものです:
変数の基本
int age = 25;
このコードは、以下のことを行っています:
int: データ型(整数を入れる箱)age: 変数名(箱の名前)=: 代入演算子(値を入れる)25: 値(箱に入れるデータ)変数の命名規則
変数名には、いくつかのルールがあります。
必須のルール:
- 英字(a-z, A-Z)またはアンダースコア(_)で始まる
- 英字、数字、アンダースコアのみ使用可能
- 予約語(
int,returnなど)は使えない - 大文字と小文字は区別される(
Ageとageは別の変数)
良い命名の慣習:
- 意味のある名前をつける(
xよりage) - 小文字とアンダースコアを使う(スネークケース):
user_name - または先頭以外を大文字に(キャメルケース):
userName - 短すぎず長すぎない
// 良い例
int age;
int student_count;
float average_score;
// 悪い例
int a; // 意味不明
int x1; // 意味不明
int numberOfStudentsInTheClassroom; // 長すぎる
int 2nd_place; // 数字で始まっている(エラー)
int my-age; // ハイフンは使えない(エラー)
---
4.2 基本データ型
整数型 (int)
int は整数(小数点のない数)を格納します。
int number = 42;
int negative = -10;
int zero = 0;
int は通常4バイト(32ビット)のメモリを使用し、約-21億から+21億の範囲の数を扱えます。
#include <stdio.h>
#include <limits.h> // INT_MIN, INT_MAX を使うため
int main(void)
{
printf("int の最小値: %d\n", INT_MIN);
printf("int の最大値: %d\n", INT_MAX);
return 0;
}
出力例:
int の最小値: -2147483648
int の最大値: 2147483647
文字型 (char)
char は1文字を格納します。
char letter = 'A';
char digit = '5';
char symbol = '@';
文字はシングルクォート(')で囲みます。
char は1バイト(8ビット)のメモリを使用します。実際には、文字を表す数値(ASCIIコード)が格納されています。
#include <stdio.h>
int main(void)
{
char letter = 'A';
printf("文字: %c\n", letter);
printf("ASCIIコード: %d\n", letter);
return 0;
}
出力:
文字: A
ASCIIコード: 65
浮動小数点型 (float, double)
小数を扱うには float または double を使います。
float pi_f = 3.14f; // float(末尾にfをつける)
double pi_d = 3.14159265; // double(より精度が高い)
float: 4バイト、約7桁の精度double: 8バイト、約15桁の精度
通常は double を使用します。
#include <stdio.h>
int main(void)
{
float f = 3.14159265358979f;
double d = 3.14159265358979;
printf("float: %.15f\n", f);
printf("double: %.15f\n", d);
return 0;
}
出力例:
float: 3.141592741012573
double: 3.141592653589790
float は精度が足りないため、値が変わってしまっています。
データ型のサイズ
sizeof 演算子でデータ型のサイズ(バイト数)を確認できます。
#include <stdio.h>
int main(void)
{
printf("char: %zu バイト\n", sizeof(char));
printf("int: %zu バイト\n", sizeof(int));
printf("float: %zu バイト\n", sizeof(float));
printf("double: %zu バイト\n", sizeof(double));
return 0;
}
出力例:
char: 1 バイト
int: 4 バイト
float: 4 バイト
double: 8 バイト
---
4.3 変数の宣言と初期化
宣言
変数を使う前に、宣言(Declaration)が必要です。
int age; // 宣言のみ
float height; // 宣言のみ
char grade; // 宣言のみ
宣言すると、メモリ上に変数のための領域が確保されます。
初期化
変数に最初の値を入れることを初期化(Initialization)と呼びます。
int age = 25; // 宣言と同時に初期化
float height = 1.75;
char grade = 'A';
宣言と代入を分ける
int age; // 宣言
age = 25; // 代入(後から値を入れる)
未初期化変数の危険性
初期化していない変数には、ゴミ(不定値)が入っています。
#include <stdio.h>
int main(void)
{
int x; // 初期化していない
printf("x = %d\n", x); // 何が表示されるかわからない
return 0;
}
これは未定義動作(Undefined Behavior)です。毎回違う値が表示されたり、プログラムがクラッシュしたりする可能性があります。
常に変数を初期化しましょう。
int x = 0; // 0で初期化
複数の変数を一度に宣言
同じ型の変数は、一行で宣言できます。
int a, b, c; // 3つのint変数を宣言
int x = 1, y = 2; // 宣言と初期化
float width = 10.5, height = 20.0;
---
4.4 printf による出力
フォーマット指定子
printf で変数の値を表示するには、フォーマット指定子(Format Specifier)を使います。
int age = 25;
printf("Age is %d\n", age);
%d が「ここに整数を表示せよ」という指示です。
主なフォーマット指定子
| 指定子 | 意味 | 例 |
|--------|------|-----|
| %d | 整数(int) | printf("%d", 42); → 42 |
| %c | 文字(char) | printf("%c", 'A'); → A |
| %f | 浮動小数点(float/double) | printf("%f", 3.14); → 3.140000 |
| %s | 文字列 | printf("%s", "Hello"); → Hello |
| %x | 16進数 | printf("%x", 255); → ff |
| %p | ポインタ(アドレス) | printf("%p", &x); |
| %% | パーセント記号 | printf("%%"); → % |
表示幅の指定
printf("%5d\n", 42); // 5桁の幅で右寄せ: " 42"
printf("%-5d\n", 42); // 5桁の幅で左寄せ: "42 "
printf("%05d\n", 42); // 5桁でゼロ埋め: "00042"
小数点以下の桁数指定
printf("%.2f\n", 3.14159); // 小数点以下2桁: "3.14"
printf("%.5f\n", 3.14159); // 小数点以下5桁: "3.14159"
printf("%10.3f\n", 3.14159); // 幅10、小数点以下3桁: " 3.142"
複数の変数を表示
int a = 10;
int b = 20;
printf("a = %d, b = %d\n", a, b);
出力:
a = 10, b = 20
フォーマット指定子の順番と、引数の順番は一致している必要があります。
実践例
#include <stdio.h>
int main(void)
{
char name[] = "Taro";
int age = 20;
float height = 175.5f;
printf("Name: %s\n", name);
printf("Age: %d years old\n", age);
printf("Height: %.1f cm\n", height);
return 0;
}
出力:
Name: Taro
Age: 20 years old
Height: 175.5 cm
---
4.5 算術演算子
基本的な演算
int a = 10;
int b = 3;
int sum = a + b; // 加算: 13
int diff = a - b; // 減算: 7
int prod = a * b; // 乗算: 30
int quot = a / b; // 除算: 3(整数の割り算)
int rem = a % b; // 剰余(余り): 1
整数除算の注意
整数同士の割り算は、小数点以下が切り捨てられます。
int result = 10 / 3; // 結果は3(3.333...ではない)
小数を得たい場合は、少なくとも一方を浮動小数点にします:
double result = 10.0 / 3; // 結果は3.333...
double result2 = (double)10 / 3; // キャスト
剰余演算子(%)
% は割り算の余りを求めます。
10 % 3 // 1(10 ÷ 3 = 3 余り 1)
15 % 5 // 0(15 ÷ 5 = 3 余り 0)
7 % 2 // 1(7 ÷ 2 = 3 余り 1)
偶数・奇数の判定によく使われます:
if (number % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
演算の優先順位
数学と同じように、、/、% は +、- より先に計算されます。
int result = 2 + 3 * 4; // 14(3 * 4 = 12、2 + 12 = 14)
int result2 = (2 + 3) * 4; // 20(括弧が優先)
迷ったら括弧を使いましょう。
複合代入演算子
int x = 10;
x = x + 5; // x は 15
// 短く書くと
x += 5; // x = x + 5 と同じ
| 演算子 | 意味 |
|--------|------|
| += | 加算して代入 |
| -= | 減算して代入 |
| = | 乗算して代入 |
| /= | 除算して代入 |
| %= | 剰余を代入 |
int x = 10;
x += 5; // x = 15
x -= 3; // x = 12
x *= 2; // x = 24
x /= 4; // x = 6
x %= 4; // x = 2
インクリメント・デクリメント
1だけ増やす・減らす専用の演算子があります。
int x = 5;
x++; // x は 6(x = x + 1 と同じ)
x--; // x は 5(x = x - 1 と同じ)
前置と後置の違い:
int x = 5;
int a = x++; // a = 5, x = 6(代入してから増加)
int b = ++x; // b = 7, x = 7(増加してから代入)
最初は混乱するかもしれません。単独で x++; と使う分には、前置・後置の違いを気にする必要はありません。
---
4.6 型変換(キャスト)
暗黙の型変換
異なる型を混ぜると、自動的に型変換が行われます。
int i = 5;
double d = i; // int から double に自動変換
printf("%f\n", d); // 5.000000
明示的な型変換(キャスト)
(型名) を使って、明示的に型変換できます。
int a = 10;
int b = 3;
double result = (double)a / b; // 3.333...
printf("%.3f\n", result);
(double)a は、a の値を double 型として扱います。
型変換の注意点
大きい型から小さい型への変換では、情報が失われることがあります。
double d = 3.99;
int i = (int)d; // i は 3(小数部分が切り捨てられる)
int big = 300;
char c = (char)big; // char の範囲を超えている
printf("%d\n", c); // 44(予期しない値)
---
4.7 定数
リテラル(直接書く値)
コード中に直接書く値をリテラルと呼びます。
42 // 整数リテラル
3.14 // 浮動小数点リテラル
'A' // 文字リテラル
"Hello" // 文字列リテラル
const修飾子
const をつけると、変更できない変数(定数)になります。
const int MAX_SIZE = 100;
const double PI = 3.14159265;
MAX_SIZE = 200; // エラー!const変数は変更できない
#define マクロ
プリプロセッサディレクティブ #define でも定数を定義できます。
#define MAX_SIZE 100
#define PI 3.14159265
int array[MAX_SIZE]; // 配列のサイズに使用
double circumference = 2 * PI * radius;
#define はコンパイル前にテキスト置換を行います。const との違いは:
| 特徴 | const | #define | |------|-------|---------| | 型チェック | あり | なし | | スコープ | あり | なし(ファイル全体)| | デバッグ | しやすい | しにくい | | メモリ | 使用する | 使用しない |
42では慣習的に #define がよく使われますが、const の方が安全です。
---
4.8 入力の受け取り(scanf)
scanf関数
ユーザーからの入力を受け取るには scanf を使います。
#include <stdio.h>
int main(void)
{
int age;
printf("Enter your age: ");
scanf("%d", &age); // &age: age変数のアドレス
printf("You are %d years old.\n", age);
return 0;
}
実行例:
Enter your age: 25
You are 25 years old.
&(アドレス演算子)
scanf では変数名の前に & をつけます。これは「変数のアドレス」を意味します。
scanf は入力された値を変数に格納するために、変数の場所(アドレス)を知る必要があるのです。
int x;
scanf("%d", &x); // &x = xのアドレス
詳細はポインタの章で学びます。
複数の入力
int a, b;
printf("Enter two numbers: ");
scanf("%d %d", &a, &b);
printf("Sum: %d\n", a + b);
実行例:
Enter two numbers: 10 20
Sum: 30
scanfの注意点
scanf には多くの落とし穴があります:
- バッファオーバーフロー(文字列入力時)
- 入力の検証がない
- 改行文字の扱い
本格的なプログラムでは、より安全な入力方法を使いますが、学習段階では scanf で十分です。
---
4.9 実践:簡単な計算機
課題:2つの数の計算
#include <stdio.h>
int main(void)
{
int a, b;
printf("Enter first number: ");
scanf("%d", &a);
printf("Enter second number: ");
scanf("%d", &b);
printf("%d + %d = %d\n", a, b, a + b);
printf("%d - %d = %d\n", a, b, a - b);
printf("%d * %d = %d\n", a, b, a * b);
if (b != 0)
printf("%d / %d = %d\n", a, b, a / b);
else
printf("Cannot divide by zero!\n");
return 0;
}
課題:温度変換
摂氏から華氏への変換プログラムを作成してみましょう。
華氏 = 摂氏 × 9 / 5 + 32
#include <stdio.h>
int main(void)
{
double celsius;
double fahrenheit;
printf("Enter temperature in Celsius: ");
scanf("%lf", &celsius); // double は %lf
fahrenheit = celsius * 9.0 / 5.0 + 32.0;
printf("%.1f°C = %.1f°F\n", celsius, fahrenheit);
return 0;
}
実行例:
Enter temperature in Celsius: 25
25.0°C = 77.0°F
---
4.10 この章のまとめ
学んだこと
- 変数
- データ型
int: 整数
- char: 文字
- float, double: 小数
- sizeof でサイズ確認- printf
%d, %c, %f, %s
- 幅と精度の指定- 演算子
+, -, , /, %
- 複合代入: +=, -=, =, /=
- インクリメント/デクリメント: ++, --- 型変換
(型名)- 定数
const 修飾子
- #define マクロ- 入力
scanf 関数
- アドレス演算子 &フォーマット指定子一覧
| 型 | printf | scanf |
|----|--------|-------|
| int | %d | %d |
| char | %c | %c |
| float | %f | %f |
| double | %f | %lf |
| 文字列 | %s | %s |
次の章の予告
次章では、条件分岐(if文)を学びます。プログラムに「判断」させる方法を覚えましょう。
---
Column: なぜintは2147483647までなのか
2進数と桁数
int が4バイト(32ビット)の場合、32桁の2進数で数を表現します。
符号なし整数なら:
- 最小値: 00000000 00000000 00000000 00000000 = 0
- 最大値: 11111111 11111111 11111111 11111111 = 4,294,967,295
- 最上位ビットが符号を表す(0: 正、1: 負)
- 32ビットのうち、1ビットが符号に使われる
負の数の表現
コンピュータは負の数を「2の補数」という方法で表現します。
そのため、符号付き int の範囲は:
- 最小値: -2,147,483,648(-2^31)
- 最大値: 2,147,483,647(2^31 - 1)
オーバーフロー
最大値を超えると、値が一周して最小値に戻ります(オーバーフロー)。
int max = 2147483647;
printf("%d\n", max + 1); // -2147483648 が表示される
これはバグの原因になりやすいので、注意が必要です。
---
確認問題
問題1
以下の宣言で正しいものはどれですか?a) int 2nd_place = 2;
b) int _score = 100;
c) int my-age = 20;
d) int float = 3.14;
解答
正しいのは b) int _score = 100; のみ。
- a) 数字で始まる変数名は不可
- c) ハイフンは変数名に使えない
- d)
floatは予約語
問題2
以下のコードの出力は何ですか?int a = 10;
int b = 3;
printf("%d\n", a / b);
解答
3
整数同士の割り算では、小数点以下が切り捨てられます。
問題3
以下のコードの出力は何ですか?int x = 5;
x += 3;
x *= 2;
printf("%d\n", x);
解答
16
x += 3→ x = 5 + 3 = 8x = 2→ x = 8 2 = 16
問題4
double 型の変数を小数点以下2桁で表示するprintfの書式は?解答
%.2f
例: printf("%.2f", 3.14159); → 3.14
問題5
scanf で int 型変数 num に値を読み込む正しい書き方は?解答
scanf("%d", &num);
変数の前に & を付けてアドレスを渡す。
---
次の章では、条件分岐を学びます。プログラムに判断力を持たせましょう!