C言語入門|13章の練習問題

ビルドの流れを楽しく理解しよう

13章では、C言語の大きな特徴である ビルドの仕組み複数ファイル分割 を学びました。
プログラムがコンパイルされて実行できる形になるまでには、いくつもの“ステップ”が存在します。

たとえば、ソースコードが書かれた sample.c が、最終的に実行可能ファイル sample になるまでには、

  • 前処理(プリプロセス)
  • コンパイル(翻訳)
  • アセンブル
  • リンク

という段階を通ります。

そして、規模の大きいプログラムでは、複数ファイルを分割し、

  • ヘッダファイル(関数の宣言)
  • ソースファイル(関数の定義)
  • main 関数を含むファイル

といった構造で整理できるようになります。

これらはプロの現場で「当たり前に」行われる作業であり、13章を理解しておくと、一気に“上級者の仲間入り”です。

ビルド工程の全体像

以下は、C プログラムが実行ファイルへ変換されるまでの流れを表で示したものです。

ビルドの流れ

フェーズ入力出力説明
前処理sample.c前処理済みソース#include 展開・マクロ置換などを実行
コンパイル前処理済みソースアセンブリコードC を低レベルの言語に翻訳
アセンブルアセンブリコードsample.o(オブジェクトファイル)機械語へ変換
リンク複数の .o + ライブラリ実行可能ファイル他ファイル・ライブラリと結合

この章で登場する命令の書式と役割

命令書式役割
gcc(コンパイル)gcc -c file.cfile.c をコンパイルして file.o を生成
gcc(リンク)gcc file.o sub.o -o prog複数のオブジェクトファイルを結合して実行ファイルを生成
#include#include <stdio.h>標準ライブラリやヘッダファイルを取り込む。
#pragma once(ヘッダの先頭に記述)同じヘッダが複数回インクルードされるのを防ぐ。
関数プロトタイプint create(int x);他ファイルにある関数を使用できるよう宣言

13章の練習問題

【練習13-1】(ビルド工程の理解)

次の図の(ア)〜(ウ)に入る語句を答えてください。

ソースファイル(game.c)
        ↓ (ア)
前処理済みソース
        ↓ (イ)
オブジェクトファイル(game.o)+ 他の .o やライブラリ
        ↓ (ウ)
実行可能ファイル(game)

【解答例】
(ア)プリプロセッサ(前処理)
(イ)コンパイラ(コンパイル)
(ウ)リンカ(リンク)

【解説】

  • プリプロセッサ
    #include や #define を展開する段階です。
  • コンパイラ
    C言語→アセンブリに翻訳します。
  • リンカ
    複数の .o ファイルやライブラリと結合して実行ファイルを作ります。

【練習13-2】(ファイル分割・別ファイル参照)

次のプログラムの greet 関数を greet.c へ分割し、同じ動作になるようにしてください。ただし、2つのファイルは同じディレクトリに保存します。

main.c(分割前)

#include <stdio.h>

void greet(void);
{
    printf("Hello from greet!\n");
}

int main(void)
{
    printf("Welcome to main!\n");
    greet();
    return 0;
}

【解答例】

main.c(分割後)

#include <stdio.h>
#include "greet.c"

int main(void)
{
    printf("Welcome to main!\n");
    greet();
    return 0;
}

greet.c (分割後)

#include <stdio.h>

void greet(void)
{
    printf("Hello from greet!\n");
}

【練習13-3】(ヘッダファイルの作成)

(1) 以下の関数 createCode を宣言するヘッダファイル code.h を作りなさい。

code.c

#include <stdlib.h>

int createCode(int limit)
{
    return rand() % limit;
}

【解答例】

code.h

int createCode(int limit);

(2) code.c に次の関数を追加し、(1)のヘッダに追記してください。

char* pickWord(int id)
{
    char* res;
    switch (id) {
        case 1:
            res = "Sky";
            break;
        case 2:
            res = "Forest";
            break;
        case 3:
            res = "Ocean";
            break;
        default:
            res = "Unknown";
    }
    return res;
}

【解答例】

code.h(ヘッダ追加後)

int createCode(int limit);
char* pickWord(int id);

code.c(関数追加後)

#include <stdlib.h>

int createCode(int limit)
{
    return rand() % limit;
}

char* pickWord(int id)
{
    char* res;
    switch (id) {
        case 1:
            res = "Sky";
            break;
        case 2:
            res = "Forest";
            break;
        case 3:
            res = "Ocean";
            break;
        default:
            res = "Unknown";
    }
    return res;
}

【練習13-4】(ヘッダ+ソース+main の連携)

(3) 上記 code.h / code.c を使い、3つの単語からランダムに1つ表示する main.c を作成しなさい。

【解答例】

main.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "code.h"

int main(void)
{
    srand((unsigned)time(NULL));

    int id = createCode(3) + 1;
    char* word = pickWord(id);

    printf("Selected word: %s\n", word);
    return 0;
}