ANSI C には「const修飾子」が導入されています。ANSI C 準拠でないCで も多くのCに導入されていて、未導入のCコンパイラは少ないでしょう。これ は要するに、定数だ、変化はしない、と宣言するものです。const修飾子はコ ンパイルの最適化を促すだけではなく、プログラムの安全性の向上、バグの撃 退に非常に効果があります。実際には最適化の効果は微々たるもので、主眼は 安全性、信頼性の向上です。
しかし、const修飾子についての解説はどのCの本を見てもわずかで、軽視 も甚だしい。少しでもプログラムの信頼性向上を図ろうとすれば非常に重要な 助っ人であり、これを無視するのは、わざわざ信頼性向上のためにC言語に導 入された機能を生かさないことになります。そういう理由で、本書ではconst を特に詳しく解説します。
次は、文字列の一部を変更するプログラムです。どういう動作をするか考え てください。
| サンプルプログラム |
1: /* strlit.c -- 文字列リテラル */ 2: 3: #include |
変数 p と q の違いが分かりましたか。pはヌル文字も含めてサイズが4の配 列です。文字列"abc"は、全て配列pの中にあり、メモリ上のその他のいずれの 場所にも存在しません。
変数qは、文字へのポインタです。"def"のように "(2重引用符)で囲んだ 文字列を「文字列リテラル」と呼びます。文字列リテラルがchar型配列の初期 値として与えられたときは、その配列に値(文字)がセットされますが、char 型へのポインタの初期値として与えられたとき、どういう動作をするでしょう か。
配列pとポインタqに対して、代入
12: p[1] = '@'; 18: q[1] = '@';をしていますが、実行結果はどうなったでしょうか。
| 実行結果 |
p : 40b0 p : abc p : a@c &q: 40b4 q : 2290 q : def Segmentation fault (core dumped) |
最後のprintf文の実行の前に、
Segmentation fault (core dumped)
が表示されています。この部分の動作はコンピュータやコンパイラによって異 なります。"Segmentation fault (core dumped)" というメッセージは、コン ピュータにできるはずのない無茶苦茶な要求をしたため、core(コア)を吐い たのです。無理矢理酒を飲ませて、ゲロを吐いたようなものです。
状況からいって、
18: q[1] = '@';
に原因があることは察せられるでしょう。ポインタqが指している先は、文字 列リテラルです。
文字列リテラルは無条件にconst修飾子がついているものと見なされます。 したがって、文字列リテラルの実体は無条件に「静的記憶領域」に置かれます。 ここで使用しているコンピュータでは、静的記憶領域を、変更可能な領域と、 変更不可能な領域に分けていて、静的でconstなものは呼び出し専用メモリ (ROM)領域に置かれます。さらに、このコンピュータでは、ROM領域は自由に 読み出せますが、書き込もうとすると無視するのではなく、コアを吐き、実行 を強制的に中断します。
アドレスは、変数pが40b0、変数qが40b4で隣り合っていますが、 qの値、つ まり実際に文字列リテラルが確保されているアドレスは2290で、少々離れてい ます。

文字列リテラルはstaticが暗黙の内についていて、必ず静的記憶領域に確保 されます。だから、たとえ関数中で使われても、文字列リテラルの実体は静的 記憶領域に確保されます。
⇒⇒⇒⇒次ページへ