C言語編 第3章 変数

先頭へ戻る

この章の概要

この章の概要です。


変数

この章では、変数について説明します。

変数とは、名前の通り「変化する数」です。 プログラムを実行している最中のある時点で 100 という数だったものが、他のある時点では 200 になっているかもしれない。 そういう数です。

「数」という表現をしていますが、実際には、文字など、数以外の場合もあります。 そこでまとめて、「値(あたい)」という言葉を使います。 100 も「a」のような文字も、全部まとめて「値」と呼ぶということです。

変数を視覚的にイメージするとすれば、「値を入れておく箱」ということになります。 ソースコード上に、この箱を用意させる記述しておけば、プログラムの実行時に、その箱が実際に使用できるようになります。

先程、冒頭部分の説明の中で、「100 だったものが 200 になっているかもしれない」という表現をしました。箱の話に直すと、「箱の中に入っていた 100 という値が、あるタイミングで 200 に変わっているかもしれない」ということです。箱の中身は、基本的に自由に出し入れできます。いつ出し入れするのか、どんな値を入れるのかは、もちろん、プログラムを書くあなたが決めることです。


宣言と定義

変数を使うにはまず、宣言という行為を行う必要があります。 宣言とは、「これからこういう変数を使いたい」という意思表明をするということです。 もちろんこれは、ソースコード上に、C言語の文法ルールに従って記述するのです。

変数を宣言するときには、変数のと、変数の名前を指定します。それぞれ、この後の項で詳細に説明します。

冒頭で登場した「箱」で考えると、変数の宣言とはいわば、箱を注文するということです。「こういうものが入れられる箱が欲しい」という注文です。注文段階なので、まだそこに「箱」がある訳ではないということになります。実際に箱が使えるようになるのは、変数の定義を行ったときです。

コンピュータ寄りの言い方をすると、定義を行ったときに、メモリという場所に、値を保存するための領域が取られます。

宣言と定義を具体的にどうやるのかは、この後説明します

変数の型

変数には、「(かた)」があります。 型とは、どのような種類の値を入れることができるのかという指定です。 つまりは、整数とか小数とか、文字とか、そういった区別です。

具体的には、次のような指定ができます。

扱える値
int 整数
char 文字(文字列ではない)
float 浮動小数点数
double 浮動小数点数(float よりも高精度)

例えば、型として「int」を選んだとすると、その変数は「int型の変数」と呼ばれます。 int型の変数の場合、整数しか入れることはできません。

char型の変数の場合、文字を1文字だけ入れておけます。1文字だけというのがポイントで、2文字以上ある文字列を入れることはできません。char型の変数を使って、文字を扱う例は、第8章で改めて取り上げます。

(文字列の変数については、第25章で説明します)。

float型 double型は、ともに浮動小数点数を扱う型です。単に、小数と言いたくなりますが、これは正確な表現とは言えません。

小数点以下には、桁が無限に続く可能性があります。そのため、コンピュータで表現するには、近似的な表現方法が必要です。表現方法の一種として、浮動小数点方式というものがあり、浮動小数点方式で表現された数のことを、浮動小数点数といいます。

浮動小数点方式は、その仕組みの都合上、どうしても誤差が発生します。表現の精度が高いほど、正確に数を表現することができるのですが、その精度の違いが、float型と double型の違いです。

例えば、「0.1」という数を扱いたくても、コンピュータの表現力では正確に表現できないかもしれません。float型では「0.100000024」のようになり、double型では「0.10000000000000007」のようになり得るということです。どちらかといえば、double型の方が正確な値に近いですが、いずれにしても、正確では無いということです。とはいえ、正確に近い方が計算のトラブルが少ないですから、基本的には、double型だけを使うようにして問題ありません

ただし、float型の方が、使うメモリの大きさが小さく済みます。また、float型の方が計算が高速である可能性もあります。ただし、速度については環境によるところが大きいので一概には言えません。

なお、浮動小数点数という言葉の代わりに、実数と表現することがありますが、実数というと整数を含んでいる印象を与えるので、気を付けて使った方が良いでしょう。

数学において実数は、有理数と無理数を含めた数とされています。有理数の中に整数が含まれています。

C言語では、int型のように整数を扱う型(整数型)と、float型のように浮動小数点数を扱う型(浮動小数点型)をまとめて、実数型と呼んでいます。

型の分類に関する一覧表が「APPENDIX 型の分類表」にあります。

浮動小数点数の詳細な話題は難しくなるので、これ以上深入りしませんが、ともかく、「浮動小数点数は正確に表現できないことがある」という点は記憶に留めておいて下さい。詳しい話は、第20章で取り上げます。

変数の名前(識別子)

変数を宣言する際に必要になる、もう1つの情報が、変数の名前です。変数名と呼ぶことも多いですが、より正確には識別子といいます。

名前が必要な理由は、変数を複数宣言したときに、それぞれの区別を付けられるようにするためです。

識別子は、以下の規則にさえ従っていれば、自由な名前を使えます。

文字数の上限は基本的にはありませんが、名前の先頭から、一定の文字数分までしか有効であるとみなさないコンパイラはあり得ます。最低でも 31文字は保証されているので、これ以内の長さに収めるようにしておくと無難です(まず問題のない長さだと思います)。

小文字と大文字は区別されるという点に注意して下さい。例えば、abc と ABC では別の名前です。プログラミング言語の種類によっては、区別しないものもあるので、そのような言語の経験者は特に注意が必要です。

記号として、アンダーバー(_) だけが使えるのが不思議かもしれませんが、他のほとんどの記号には別の用途があるので、識別子としては使えません。「_」は主に、長い名前を付ける際の単語の区切りに使います。

なお、「_」を名前の先頭の文字に使うことは、許可されてはいますが、避けるのが無難です

これは、コンパイラ側が使う識別子として予約されているためです。厳密には、場面次第では問題なく使える場合もありますが、ややこしいので、先頭の文字を「_」にしない、というように覚えておくのが妥当だと思います。

また、C言語が機能を提供するために、幾つかの名前を使用しています。例えばこれまでに、return、int、char、float、double、void といったものが登場しました。こういったキーワードと同じ名前は使うことができません。すべてのキーワードを、APPENDIX「キーワードの一覧表」にまとめてあります。

名前は、後でソースコードを見直したときにも、どのような用途で使っているのかが分かりやすいように付けるべきです。この辺りは経験も必要ですが、意識していくようにしましょう。

変数を使う

それでは、変数を使ったプログラム例を見てみましょう。

#include <stdio.h>

int main(void)
{
    int num;

    num = 100;
    printf( "%d\n", num );

    return 0;
}

実行結果:

100

何をしているのか、順番に確認していきます。

宣言と定義

main関数の1行目にある「int num;」の部分で、変数を宣言および定義しています。この記述により、int型で、名前が num という変数が宣言され、実際に使える状態(定義された状態)になります。

現時点では、変数の宣言と定義が分かれているような例は登場しません。第23章で登場する extern を使うと、変数の宣言だけを行えます。

この時点では、変数には値が何も入っていない訳ではなくて、何かよく分からない値が入っています。int型の変数なら、0 が入っていそうな感じがするかもしれませんが、そうではありません。このような、何か分からない値を不定値と呼びます。

不定値はどんな値か分からないので、不定値が入っている変数の値を使うようなプログラムは、どんな結果になるか分かりません。そのため、避けなければなりません。変数の値を使う前には、きちんと、具体的な値を入れてやる必要があります。

なお、num は numeric という英単語の略で「数値」という意味です。このような名前は、サンプルプログラムでよく使われますが、あまり良い名前の付け方ではありません。その変数がどんなことに使われるのかを表すような名前を付けるのが良いです。

例えば、「得点」を表しているのなら「score」のようにするということですが、「英語の得点」と「数学の得点」が必要だったら「english_score」と「math_score」のように、更に区別が付けられるようにする必要があるかもしれません。

代入

不定値が入った変数の値を使わないようにするためには、具体的な値を入れてやればよいです。これをしているのが、「num = 100;」という部分です。この記述によって、変数 num に 100 という値が入ります。

「=」は一般的には「イコール」の記号ですが、C言語のこの記号には「同じ」という意味はありません。惑わされないようにして下さい。

このように、変数に値を入れる操作のことを、代入といいます。代入を行うと、それまで変数に入っていた元の値は消えてなくなり、新しい値に書き変わります。つまり、上書きしたことになります。

ここで、ソースコード上に書かれている「100」という値は、決して変化することがありませんから、定数と呼ばれます。

代入は、定数を変数に入れるような使い方のほかに、変数の値を変数に入れるような使い方もあり得ます。

#include <stdio.h>

int main(void)
{
    int num1;
    int num2;

    num1 = 100;
    num2 = num1;
    
    printf( "num1: %d\n", num1 );
    printf( "num2: %d\n", num2 );

    return 0;
}

実行結果:

num1: 100
num2: 100

「num1 = 100;」は、定数 100 を変数 num1 へ代入しています。「num2 = num1;」の方は、変数 num1 に入っている値を変数 num2 へ代入しています。

「num2 = num1;」によって、変数 num2 の値は、変数 num1 に入っていた 100 になります。代入が行われても、変数 num1 の方の値は変化しないことを理解して下さい。変数に入っている値を移し替えているのではなく、コピーしているようなイメージが適切です。

文字列以外の値を出力する

printf関数の使い方にも注目です。前章では文字列を出力していましたが、今回出力したいものは数字なので、違う書き方をしています。

printf関数に指定する文字列の中に、"%d" という文字列を入れると、その部分を数字で置き換えられます。この機能を使って、「printf( "%d\n", num );」と書けば、"%d" の部分が、変数num の値で置き換えられます。printf関数において、"%d" のような特殊な意味を持った文字列は、変換指定子と呼ばれています。変換指定子は以下のように幾つかの種類があります。

変換指定子 意味
%d 整数
%f 浮動小数点数
%c 文字
%s 文字列

これで全てではありませんが、当面必要になるのはこれくらいでしょう。完全なリストは、リファレンスを参照して下さい。

変換指定子は、一度に複数個使うことも可能です。例えば、「printf( "%d は %d の 10倍\n", 100, 10 );」のような記述も許されます。この場合、最初に現れた "%d" に 100 が、次に現れた "%d" に 10 が埋め込まれます。

この機能は非常に便利で強力なものですが、使い方を誤ると大変です。例えば、"%d" が 3回登場するのに、具体的な値の指定が 2個しかないと、最後の "%d" の扱いが不明確になり、正しい出力が得られません。

なお、「\」「%」「"」は、printf関数を使う際に別の意味で登場する特殊な文字です。

「\」は「\n」のように使って改行を意味するなど、ほかの文字との組み合わせで何らかの意味を持ちます。「%」は先ほどの "%d" のような特殊な指定を意味しています。「"」は、文字列を取り囲む「""」の片割れです。このような、別の意味を持っている文字を、そういった意味を無視して出力させたいときには、「\\」「%%」「\"」といった書き方をしなければなりません。

変数の初期化

先ほどの例では、変数を宣言した後で値を代入していましたが、宣言と同時に値を与えることもできます。

#include <stdio.h>

int main(void)
{
    double d = 3.5;

    printf( "%f\n", d );

    return 0;
}

実行結果:

3.500000

今回は double型の変数にしてみました。変数d を宣言するのと同時に、3.5 という値を与えています。宣言と同時に値を与えれば、不定値が入った変数をうっかり使ってしまうミスを防げます。そのため、原則として、この方法を使うようにするべきです。

このように、変数を宣言するときに値を与えることを初期化といい、与える値を初期値といいます。

初期値を指定する際には、「int a = 0;」のように定数を指定するほか、「int b = a;」のように、他の変数の値を使うことも可能です。いずれにしても、「=」の右側の内容を処理した結果が初期値となります。つまり、初期値を作り出して、それを変数に与えていると考えられます。このように、初期値を指定するものを初期化子と呼びます。

初期化子は、初期値を指定する式です。「式」は値を生み出します(第27章)。「0」のような定数も式ですし、「a」のような識別子だけの場合も式です。また、「int b = a + 2;」のような計算式(第4章)を使うこともできます。


練習問題

問題① 次のうち、変数名として使えないものを全て選んで下さい。

問題② 不定値を、printf関数で出力してみて下さい。

問題③ printf関数の "%d" 変換指定子を使って、浮動小数点数を出力するとどうなるか試してみて下さい。

問題④ 次のプログラムの実行結果を答えて下さい。

#include <stdio.h>

int main(void)
{
    int a = 10;
    int b = 20;

    printf( "a: %d, b: %d\n", a, b );
    
    a = b;
    printf( "a: %d, b: %d\n", a, b );
    
    b = 30;
    printf( "a: %d, b: %d\n", a, b );
    
    a = b;
    printf( "a: %d, b: %d\n", a, b );

    return 0;
}


解答ページはこちら

参考リンク



更新履歴

'2018/5/18 「変数の名前」の項を修正。項の名前を「変数の名前(識別子)」に変更し、内容を見直した。

'2018/5/16 「変数の初期化」の項を修正。「初期値」と「初期化子」を明確にした。

'2018/5/11 章のタイトルを変更(「変数を宣言する」->「変数」)
変数を使う」の項を細分化し、「定数」の説明を追加。変数から変数への代入について追記。
練習問題に問題④を追加。

'2018/5/3 「キーワードの一覧表」へのリンクを追加。

'2018/1/27 全面的に文章を見直し、修正を行った。

≪更に古い更新履歴を展開する≫



前の章へ(第2章 Hello, Worldプログラム)

次の章へ(第4章 計算の仕方)

C言語編のトップページへ

Programming Place Plus のトップページへ


はてなブックマーク Pocket に保存 Twitter でツイート Twitter をフォロー
Facebook でシェア Google+ で共有 LINE で送る rss1.0 取得ボタン RSS
管理者情報 プライバシーポリシー