読者です 読者をやめる 読者になる 読者になる

C言語 定数 const

C言語改訂版2 はじめて学ぶCの仕組み (CD-ROM付) (プログラミング学習シリーズ)

C言語改訂版2 はじめて学ぶCの仕組み (CD-ROM付) (プログラミング学習シリーズ)

定数(const)というものが取り上げられている。何でも、

『動かさないと分からないミス』を『コンパイルの時に見つかるミス』

に変えてくれる

らしい。基本的な発想は、

 コンパイルエラーはエラー箇所を指定してくれるから楽

であり、

 コンパイル時に(必要なら)エラーが発生するように文字に制限をかける

というのが基本的発想か。あと、#defineは型の指定が無く、有効範囲が固定的(ファイル内)であるため、文字に定数の制限をかけるならやはりconstの使用が良いということか。

ポインタ変数とセットで使う場合が少しややこしく感じる。パターンは3つ。ポインタ変数は、メモリの住所の受け皿(住所を与えることで住所の先にある変数に対して処理を行うための変数)という理解をしていたことに注意すると、

     Int *const p     ポインタ変数の値を固定する

     const Int  *p                ポインタ変数pの指す住所を固定する

        const Int *const p    両者を固定する

試してみよう。

#include <stdio.h>
#include <stdlib.h>

main () {
        char *const p = "Hello";       //1.ポインタ変数のショートカット先を固定
        const char *q = "new";        //2.ポインタ変数の指すショートカット先の内容を固定
        const char *const r = "world";   //3.両方を固定

        p = "Good-bye";      //エラー9:2:に対応(1.よりショートカット先は変更できない)
        q = "old";      //エラーなし(2.よりショートカット先の指定は可能)
        *q = "old";      //エラー11:2:に対応(2.よりショートカット先の内容は変更できない)
        r = "Japan";     //エラー12:2:に対応(3.よりショートカット先の変更は出来ない)

        puts(p);
        puts(q);
        puts(r);
}

コンパイルの結果は…

constprac.c: 関数 ‘main’ 内:
constprac.c:9:2: エラー: 読み取り専用変数 ‘p’ への代入です
constprac.c:11:2: エラー: 読み取り専用位置 ‘*q’ への代入です
constprac.c:12:2: エラー: 読み取り専用変数 ‘r’ への代入です

要は、ポインタ変数に対してconstを使う場合は、ポインタ変数の指す住所を固定するか、ポインタ変数に代入する変数を固定するか、そのどちらかである、という意味と理解した。

【追記】

よく使うのは "const char *q"(ポインタの指す住所を固定する)のパターンの法が多いようだ。関数作成次に引数を変更して欲しくない場合に、この形で引数を書くらしい。本では、

    アドレスを受ける引数はすべてconstにしてしまえ

とまで書いている。これによって、関数中で引数が書き変わるのをコンパイル時に特定することが出来る(同じ関数中で引数が書き変わる場合はエラーが、別の関数で同じ引数が書き変わる場合は警告が出る)とのこと。

【追記】

ここの【追記】でも確認したことを踏まえると、const Int  *pはウィンドウズでショートカットからファイルを開いたときの編集にロックをかけることに対応し、Int *const pはショートカットする先をロックすることに対応する、と理解した。