1年後期,2年前期向けに担当している,Cプログラミングの授業では,constはあまり積極的には取り上げていません.とはいえ,strlenなどで出現するので,文法として知っておかないといけません.そこで,最低限のことを説明しています.具体的には以下の3点です.
- const修飾された変数は,その値を変更できません.
- 文字列を操作するいくつかの標準ライブラリ関数では,仮引数となるポインタ変数がconst修飾されています.
- Tを任意の型として,T *型のポインタ変数の値をconst T *型のポインタ変数に代入するのは問題ありません*1.
さて…
●ルール2
http://eetimes.jp/article/23004/2.html
次の条件に当てはまる場合は、常にconst修飾子を使って宣言する。
(略)
(2)関数に値を参照(ポインタ)で渡し(call-by-reference)、その値を関数内で変更することがないならば、その関数の宣言時にその引数にconst修飾子を付ける。例「char const *p_data」。
(略)
これらの理由は、コンパイラの機能を使ってデータをリード・オンリーにして、意図しない書き込みからデータを保護するためである。
少し探すと,原文も見つかりました
Rule: The const keyword shall be used whenever possible, including:
(snip)
- To define call-by-reference function parameters that should not be modified (e.g., char const * p_data),
(snip)
http://www.embeddedgurus.net/barr-code/2009/03/coding-standard-rule-2-use-const.html
Reasoning: The upside of using const as much as possible is compiler-enforced protection from unintended writes to data that should be read-only.
何に引っかかったのかというと,「char const *p_data」のところです.
文法上,これは「const char *p_data」と等価です.どちらを使うべきかは,プログラマの好みがあるでしょうし,複数人で書くなら,コーディング標準として定めれば済む話です.
ただ,「char const *p_data」を見ると,「char *const p_data」と書きたかったのか,と思わずにはいられません.
この2つの宣言は,意味が異なります.すなわち,
- const char *p_dataあるいはchar const *p_dataと宣言し,この変数に適切な値が代入されたとき,
- p_dataの指し示す先の値(*p_dataだけでなくp_data[2]といった値も)は変更できません.
- p_dataの持つ値を,char *型のポインタ変数に代入することはできません.
- p_dataの持つ値は変更できます.すなわち p_data++; と書くことができます.
- char *const p_dataと宣言し,この変数に適切な値が代入されたとき,
- p_dataの指し示す先の値(*p_dataだけでなくp_data[2]といった値も)は変更できます.
- p_dataの持つ値を,char *型のポインタ変数に代入することもできます.
- p_dataの持つ値を変更することはできません.すなわち p_data++; と書くことができません.
理由のところや,実用から,「char const *p_data」はこれが意図であり「char *const p_data」の語記ではないことが,想像できます.
しかしながらconstは,ポインタを絡めた変数宣言で上記の通り混乱しやすいので,それを避けるためにも,const使用のルールを決めるべきですね.「俺コーディング標準」なら,こんなところ.
- const修飾をするのは以下のいずれかとする.
- 型付きの定数を宣言するとき.
- 関数の仮引数の宣言で,指し示す先(典型的には,配列の中身)を書き換えないことを明示するとき.
- const修飾されているポインタ型の値が代入される変数を宣言するとき*2.
- const修飾を持つポインタ変数は,「const T *var」の形式で宣言し,「T const *var」の形式は使用しない.また「const *T var」の形式は使用しない.
そういえば,constについては過去に書いていました:constの使い道 - わさっき