第4章:データを扱う

この章で学ぶこと

  • 変数とは何か
  • 基本的なデータ型(int, char, float, double)
  • 変数の宣言と初期化
  • 基本的な演算
  • printfによる値の表示
  • 定数とマクロ
  • ---

    4.1 変数とは

    データを入れる箱

    変数(Variable)は、データを保存するための「箱」です。

    日常生活で例えると、変数は「ラベルの付いた引き出し」のようなものです:

  • 引き出しに名前を付ける(変数の名前)
  • 引き出しの大きさを決める(データ型)
  • 引き出しに物を入れる(値の代入)
  • 引き出しから物を取り出す(値の参照)
  • 変数の基本

    int age = 25;
    

    このコードは、以下のことを行っています:

  • int: データ型(整数を入れる箱)
  • age: 変数名(箱の名前)
  • =: 代入演算子(値を入れる)
  • 25: 値(箱に入れるデータ)

変数の命名規則

変数名には、いくつかのルールがあります。

必須のルール:

  • 英字(a-z, A-Z)またはアンダースコア(_)で始まる
  • 英字、数字、アンダースコアのみ使用可能
  • 予約語(int, return など)は使えない
  • 大文字と小文字は区別される(Ageage は別の変数)

良い命名の慣習:

  • 意味のある名前をつける(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
  • 負の数の表現

    コンピュータは負の数を「2の補数」という方法で表現します。

  • 最上位ビットが符号を表す(0: 正、1: 負)
  • 32ビットのうち、1ビットが符号に使われる

そのため、符号付き 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 = 8
  • x = 2 → x = 8 2 = 16

問題4

double 型の変数を小数点以下2桁で表示するprintfの書式は?

解答

%.2f

例: printf("%.2f", 3.14159);3.14

問題5

scanfint 型変数 num に値を読み込む正しい書き方は?

解答

scanf("%d", &num);

変数の前に & を付けてアドレスを渡す。

---

次の章では、条件分岐を学びます。プログラムに判断力を持たせましょう!