基本構文

C言語の基本構文を学ぶのは、漢字の筆画を学ぶようなものです——横、縦、左払い、右払いはシンプルに見えますが、美しい文字はすべてそこから構成されています。

プログラムの構造

すべての C言語プログラムは決まった骨格を共有しています。プログラムがどんなに複雑になっても、コア構造は同じです:

C
#include <stdio.h>

int main(void) {
    return 0;
}

これは最小の有効な C言語プログラムです——何もしませんが、構造は完璧です。分解してみましょう:

プリプロセッサディレクティブ

#include <stdio.h> はプリプロセッサディレクティブです。# で始まり、コンパイルの前に処理されます。

他にもよく使うヘッダファイルがあります:

ヘッダ 提供する機能
<stdio.h> 入出力(printf、scanf)
<stdlib.h> 一般ユーティリティ(malloc、exit)
<math.h> 数学関数(sqrt、sin)
<string.h> 文字列操作(strlen、strcpy)
<ctype.h> 文字分類(isdigit、toupper)

main関数

C
int main(void) {
    return 0;
}
🔥 よくある間違い: main は C言語プログラムの唯一の開始点です。main 関数は 1 つしか持てません——オペレーティングシステムがこれを呼び出してプログラムを開始します。

mainの別の形式

教科書によっては異なる形式の main を見かけることがあります:

C
int main(int argc, char *argv[])

この形式はコマンドライン引数を受け取ることができます。詳細は後で解説します。今は int main(void) で十分です。

⚠️ 注意: 古い教科書には void main() が使われていることがありますが、これは標準 C言語ではなく、一部のコンパイラは警告を出します。常に int main(void) を使ってください。

文とセミコロン

C言語では、セミコロン ; が文の終わりを示します。文章の末尾に句点(。)が必要なように、文にはセミコロンが必要です。

C
int age = 18;
age = age + 1;
printf("私は %d 歳です\n", age);

それぞれの行が 1 つの文で、セミコロンで終わっています。

よくある間違い——セミコロンの忘れ:

C
int age = 18

コンパイラは「改行」を認識しません——認識するのはセミコロンだけです。理論上はすべてのコードを 1 行に書くこともできます:

C
int age = 18; age = age + 1; printf("%d\n", age);

構文上は有効ですが、推奨されません。良いコーディングスタイルは 1 行に 1 文です。

💡 ヒント: 単独のセミコロンも有効な文で、空文と呼ばれます——何もしません:

C
;

特定の場合(空のループ本体など)で役立ちますが、今は気にする必要はありません。

コードブロック

波括弧 {} で囲まれた一連の文がコードブロック(複合文とも呼ばれる)を形成します:

C
int main(void) {
    int x = 10;
    int y = 20;
    int sum = x + y;
    printf("合計 = %d\n", sum);
    return 0;
}

main 関数の本体全体が 1 つのコードブロックです。コードブロックはスコープを定義します——ブロック内で宣言された変数はブロック外からアクセスできません。

コードブロックはネスト(入れ子)にできます:

C
int main(void) {
    int a = 1;
    {
        int b = 2;
        printf("a + b = %d\n", a + b);
    }
    return 0;
}

内側のブロックは外側の a にアクセスできますが、外側のブロックは内側の b にアクセスできません。

⚠️ 注意: コードブロックに文が 1 つしかない場合でも、波括弧を付けるのがベストです。後から文を追加したときに括弧を付け忘れるバグを防げます。

printf関数

printf は C言語で最もよく使われる出力関数です。名前は print formatted(フォーマット出力)に由来します。

基本的な使い方

C
printf("Hello, World!\n");

二重引用符の中の内容はフォーマット文字列と呼ばれ、エスケープ文字を除いてそのまま出力されます。

フォーマット指定子

printf の強みは、変数の値をフォーマットして出力できることです:

C
int age = 18;
float height = 1.75f;
char grade = 'A';
printf("年齢: %d\n", age);
printf("身長: %.2f\n", height);
printf("成績: %c\n", grade);

よく使うフォーマット指定子:

指定子 出力例
%d int 42
%f float / double 3.140000
%.2f float(小数点以下 2 桁) 3.14
%c char A
%s 文字列 hello
%ld long 100000
%x 16 進整数 2a
%o 8 進整数 52
%% パーセント記号そのもの %
💡 ヒント: 1 つの printf で複数の指定子を使えます——引数の順序に対応します:

C
int a = 3, b = 4;
printf("%d + %d = %d\n", a, b, a + b);

幅と配置

C
printf("[%5d]\n", 42);
printf("[%-5d]\n", 42);
printf("[%05d]\n", 42);
TEXT
[   42]
[42   ]
[00042]

エスケープ文字

文字列の中で直接入力できない文字(改行やタブなど)は、バックスラッシュ \ で始まるエスケープ文字で表します:

エスケープ 意味
\n 改行 printf("A\nB") は A と B を別の行に出力
\t 水平タブ 整列出力によく使用
\\ バックスラッシュそのもの \ を出力するには \\ と書く
\" 二重引用符 文字列中に " を出力
\' 単一引用符 文字リテラル中に ' を出力
\0 ヌル文字 文字列の終端を示す
\r 復帰 カーソルを行頭に移動
\b バックスペース カーソルを 1 つ左に移動
⚠️ 注意: ファイルパスを出力する際は、バックスラッシュを 2 つ重ねる必要があります:

C
printf("C:\\Users\\admin\\file.txt\n");
TEXT
C:\Users\admin\file.txt

コメント

コメントは人間のためのメモです——コンパイラは完全に無視します。良いコメントはコードを理解しやすくします。

1 行コメント

C99 では // 形式の 1 行コメントが導入されました。// から行末までがコメントです:

C
int score = 100;

複数行コメント

/* */ 形式のコメントは複数行にまたがれます:

C
/*
 * このプログラムは
 * 2 つの数の合計を計算する
 */
#include <stdio.h>

int main(void) {
    int a = 10;
    int b = 20;
    printf("%d\n", a + b);
    return 0;
}

コメントのベストプラクティス

コメントはなぜ(理由)を説明すべきで、何を(当たり前のこと)は説明不要です。コード自体が何をしているかはすでに語っています——コメントは、コードでは表現できない設計意図や判断を補足するものです。

良いコメント:

C
int max_retries = 3;

不要なコメント(コードですべてを説明済み):

C
int x = 10;
⚠️ 注意: 複数行コメントはネストできません。次のコードはコンパイルエラーになります:

C
/*
  /* ネストされたコメント */
*/

内側の */ が外側のコメントを途中で閉じてしまい、残りの */ が構文エラーになります。

識別子とキーワード

識別子の名前規則

識別子は自分で作る名前(変数名、関数名など)です。次の規則に従う必要があります:

有効な名前:agestudent_name_countMAX_SIZE

無効な名前:2name(数字で始まる)、my-age(ハイフンを含む)、int(キーワード)

命名規約

スタイル 形式 用途
snake_case 小文字 + アンダースコア 変数名、関数名 student_count
UPPER_CASE すべて大文字 + アンダースコア 定数 MAX_BUFFER_SIZE
CamelCase 各単語の先頭を大文字 カスタム型名 StudentInfo

C言語は伝統的に snake_case を使い、Java/C# のように camelCase は好まれません。最も重要なのは、プロジェクト内で一貫性を保つことです。

C99のキーワード

C99 には 37 のキーワードがあり、すべて小文字です:

分類 キーワード
データ型 char short int long float double void signed unsigned _Bool _Complex _Imaginary
制御フロー if else switch case default for while do break continue goto return
記憶域クラス auto extern static register typedef inline
構造体 struct union enum
その他 const volatile sizeof restrict

これらを暗記する必要はありません——練習を重ねれば自然に覚えます。重要なのはキーワードは識別子として使えないということだけ知っておけば大丈夫です。

この章の内容をすべて組み合わせたプログラムで、基本構文を実演します:

C
#include <stdio.h>

int main(void) {
    printf("=== 学生情報 ===\n");
    printf("名前:\t%s\n", "Alice");
    printf("年齢:\t%d\n", 20);
    printf("得点:\t%.1f\n", 95.5);
    printf("成績:\t%c\n", 'A');
    printf("================\n");
    return 0;
}
▶ 試してみよう
TEXT
=== 学生情報 ===
名前:	Alice
年齢:	20
得点:	95.5
成績:	A
================

このプログラムは次の要素を実演しています:#include プリプロセッサディレクティブ、main 関数の構造、printf フォーマット出力、\n 改行、\t タブ整列、そして 4 つの一般的なフォーマット指定子(%d%.1f%c%s)です。

❓ よくある質問

Q なぜ C言語は改行ではなくセミコロンで文を区切るのですか?
A C言語では 1 つの文を複数行にまたげるし、1 行に複数の文も書けるからです。セミコロンは区切りとしてより柔軟で、コンパイラはコードのフォーマットを気にする必要がありません。
Q printf の「f」は何の略ですか?
A 「f」は「formatted」の略です。printf は固定テキストを出力するだけでなく、%d や %f などの指定子を使って変数の値を出力に挿入できます。それが「フォーマット出力」の意味です。
Q コメントが多すぎるとプログラムが遅くなりますか?
A 全く影響しません。コンパイラはプリプロセス段階ですべてのコメントを削除するため、コンパイルされた実行ファイルにはコメントの内容が一切含まれません。好きなだけ書いてください——パフォーマンスには影響しません。
Q void main と int main のどちらを使うべきですか?
A 常に int main(void) を使ってください。C言語の規格は main が int を返すことを明確に要求しています。void main は一部の古いコンパイラの非標準拡張であり、最近のコンパイラは警告を出したり拒否したりすることもあります。

📖 まとめ

📝 練習問題

  1. printf を使って自分の情報カード(名前、年齢、趣味)を表示するプログラムを書いてください。\t で整列させること
  2. printf の呼び出し 1 回で次の内容を出力するプログラムを書いてください(エスケープ文字で改行とタブを使用):名前 Alice、年齢 25、都市 London
  3. 意図的にコードにネストされた複数行コメントを書き、コンパイラのエラーメッセージを観察してください
100%