答え
引数が
char *
だと文字列を書き換えられてしまいそう……。
void Greet(char *pName) {
引数を
const char *
にすれば安心して呼び出せる!
void Greet(const char *pName) {
解説
だいたいの場合、関数の引数をポインタにする目的は次の2つのどちらかです。
- 大きなデータを効率的に参照するため
- 値を書き込むため
この2つは意味が違うので、const
キーワードを使って区別します。つまり、値を参照したいだけのときはconst
を付けて、「このポインタはデータを受け取るためのものですよ」という意思表示をするのです。const
が付いていない場合は、「このポインタが指しているデータを書き換えますよ」という意思表示になります。
こうした作法は、全体を見渡せる程度の小さなプログラムではそれほど問題にはなりません。でも、プログラムが大きくなってくると、だんだん馬鹿にできなくなってきます。関数を呼び出すときに、いつも中身まで見えるとは限らないからです。
標準関数も、使うときには中身が見えないので、やはり作法に則って作られています。例えば、文字列の長さを数えてくれるstrlen()
は、こういう風になっています。
size_t strlen(const char *s);
const
が付いているので、文字列を受け取るための引数だということが明確ですね。
では、文字列をコピーするときに使うstrncpy()
はどうでしょうか。
char *strncpy(char *dest, const char *src, size_t n)
第1引数はコピー先なのでconst
なし、第2引数はコピー元なのでconst
ありとなっています。const
の有無が、関数の使い方を示すさりげないヒントになっていることが分かるでしょう。
こういうさりげない作法ができると、プロって感じがするわよね。
デスヨネ〜。(今度やってみよう)
ここがポイント!
データを受け取るためにポインタを引数にするときは、
const
を付けよう!
修正後のプログラム
main.c
#include <stdio.h>
#include <stdlib.h>
void Greet(const char *pName) { /* ← const を追加 */
printf("Hello, %s!\n", pName);
}
int main(void) {
Greet("Leo");
return EXIT_SUCCESS;
}
実行結果
Hello, Leo!