C言語基礎|プログラムの要素と書式

はじめに:Cのプログラムは「単語」と「区切り」の組み立てでできてるよ

C言語のソースコードって、一見すると記号だらけでゴチャっと見えがちなんだけど、正体はシンプルで、キーワード・識別子・演算子・区切り子・定数みたいな「部品」を並べて作っています。
そしてもう一つ大事なのが、見た目(書式)。Cは自由形式なので、同じ動作でもいろんな書き方ができる反面、読みやすさは自分で守る必要があります。

この節では「プログラムを構成する要素」と「書式(読みやすく書くルール)」をまとめて整理していきますね。

サンプルプログラム:九九(1〜9)を表示して、書式の違いを比べる

提示されている自由形式の例はそのまま使わず、別のプログラム例として「九九(1〜9)」を扱います。
メッセージも別の日本語に置き換えています。

読みやすい書き方(おすすめ)

プロジェクト名:chap4-20-1 ソースファイル名:chap4-20-1.c

#include <stdio.h>

int main(void)
{
    puts("九九(1〜9)を表示します。");

    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= 9; j++) {
            printf("%3d", i * j);
        }
        putchar('\n');
    }

    puts("表示が終わりました。");
    return 0;
}

あえて読みにくくした書き方(動くけど、目がつらい)

※同じ結果が出ます。でも、読みにくいので真似しないでOKです。

#include <stdio.h>
int main(void){puts("九九(1〜9)を表示します。");for(int i=1;i<=9;i++){for(int j=1;j<=9;j++){printf("%3d",i*j);}putchar('\n');}puts("表示が終わりました。");return 0;}

ポイント:Cは自由形式なので、改行や空白の入れ方で動作は変わらないことが多いけど、読みやすさは天と地ほど変わります。

キーワード:特別な意味を持つ予約語

if や for みたいな語は、C言語のルールとして意味が決められている「予約語」です。だから変数名などには使えません。

よく出てくるキーワード例

キーワード役割
if / else条件分岐
for / while / do繰り返し
break / continueループ制御
return関数から戻る
int / char / double

※Cにはたくさんキーワードがありますが、最初は「よく出るやつ」から覚えれば大丈夫です。

演算子:計算・代入・比較などをする記号

演算子は、値を計算したり、比較したり、代入したりするための記号です。
そして重要ルールがひとつ。

複数文字でできた演算子の途中に空白は入れられません。

空白を入れられない演算子の例

正しい間違いなぜダメ?
i <= 9i < = 9< と = が別物に分かれてしまう。
sum += xsum + = x+ と = が別物に分かれてしまう。
i++i + +解釈が変わってしまう可能性がある。

識別子:変数名・関数名など「あなたが付ける名前」

識別子は、変数・関数などの名前のこと。ルールはざっくり次の通りです。

  • 先頭は数字にできない。
  • 2文字目以降は英字・数字・_ が使える。
  • 大文字と小文字は区別される。

識別子の例(OK / NG)

種類
OKx, total, sum2, abc_def, maxValue
NG123, 9pc, abc$, abc@def, if

注意
下線で始まる名前(例:_x)や、特定の形は処理系が内部で使うことがあるので、基本は避けるのが安全です。

区切り子:空白がなくても意味が分かれる「しきり」

キーワードや識別子の間は、基本的に区切りが必要です。
でも、( ) や { } や ; みたいな区切り子があると、空白がなくても読めます。

主要な区切り子(よく出るもの)

区切り子役割
( )関数呼び出しや条件式の囲み
{ }複数の文をまとめる(複合文)
[ ]配列の添字
,引数や並びの区切り
;文の終わり
:case ラベルなど
#前処理指令(行頭で使う)

定数と文字列リテラル:値そのものを書いたもの

  • 数値定数:10, 3.14 など
  • 文字定数:'A', '\n' など(型は int 扱い)
  • 文字列リテラル:"Hello" など

文字定数と文字列リテラルの違い

種類意味
文字定数'A'1文字
文字列リテラル"A"文字の並び(たまたま1文字でも別物)

自由形式だけど「やっちゃダメ」な3つのこと

Cは自由形式ですが、自由には限界があります。ここは超重要です。

自由形式のNG例

NG内容何が起きる?
単語の途中で改行や空白を入れるret↵urnキーワードが壊れる
前処理指令を途中で改行する#include↵<stdio.h>原則NG(エラーになりやすい)
文字列や文字定数の途中で改行する"ABC↵DEF"文字列が壊れる

隣接した文字列リテラルは連結される

Cにはちょっと便利なルールがあります。
隣り合う文字列リテラルは、1つに連結されます。

puts("Hello, "
     "world!");

これは "Hello, world!" と同じ意味になります。長い文章を読みやすく書けるので便利です。

インデント:見た目を整えて「構造」を見えるようにする

インデントは動作には直接関係しないけど、人間の理解速度に直結します。

インデントで見える構造(九九の抜粋)

for (i = 1..9) {
    for (j = 1..9) {
        print(i*j)
    }
    newline
}

説明

  • 外側の for が「行」
  • 内側の for が「列」
  • ブロック { } の内側が1段深くなることで、入れ子関係がひと目で分かる。

登場する命令(関数など)の書式と役割

この節のサンプルで使った関数をまとめておきます。

命令書式何をする命令?
putsputs(文字列);文字列を表示して改行する。
printfprintf(書式, 値, ...);書式を指定して表示する。
putcharputchar(文字);文字を1つ表示する。
returnreturn 値;関数を終了して値を返す。