/* 仮引数の値を変更してみる (仮引数がポインタの場合) param2.cpp */ #include <stdio.h> void f1( int * a ) { *a = 10; printf( "*a is %d\n", *a ); } int main( void ) { int i = 100; f1( &i ); printf( "i is %d\n", i ); getchar( ); return 0; }
/* int型の2つの変数の値を交換するmyswap関数を完成させよ。main関数の局所変数iとjの初期値が何であっても両者の値が入れ替わるようにmyswap関数を定義すること。 myswap.cpp */ #include <stdio.h> void myswap( -----ここを完成させる------ ) { ここを完成させる } int main( void ) { int i = 5, j = 10; myswap( &i, &j ); printf( "i is %d\n", i ); /* i is 10 と表示される */ printf( "j is %d\n", j ); /* j is 5 と表示される */ getchar( ); return 0; }正解例
#include <stdio.h> void myswap( int * p1, int * p2 ) { int t; t = *p1; *p1 = *p2; *p2 = t; } int main(void) { int i = 5, j = 10; myswap(&i, &j); printf("i is %d\n", i); /* i is 10 と表示される */ printf("j is %d\n", j); /* j is 5 と表示される */ getchar(); return 0; }
なお,このように仮引数にポインタを使う引数の渡し方を『アドレス渡し』と呼ぶ。
アドレス渡しの持つメリットは,他にも
大きいデータを関数に渡す場合に,サイズが大きい
データそのもの引数にするより,ポインタだけを渡した方が,値のコピーにかかる時間が
少なくて済むというてっが挙げられる。
■ポインタで参照している対象を保護(内容を変更されないように)するには
ポインタで参照する対象(T型変数)を定数に指定して保護するには,const をつけたポインタ型
const T *
で参照してやれば良い(下図)。なお,ポインタ変数自体をconst定数にするには,ポインタ変数を
T * const
型で宣言すれば良い(下図)。
■引数の保護
仮引数の宣言を const T * 仮引数 とすると,仮引数のポインタで指し示している対象の値
を変更できなくなる。 たとえば, void f( const int * p ) { *p = 10; } とすると青字部分が
コンパイルエラーになる。
ポインタ仮引数を使う関数では,
・ポインタ引数が指している変数(T型)を変更しない場合は,ポインタ仮引数は const T * 仮引数 とする。
・ポインタ引数が指している変数(T型)を変更する場合は,単に T * 仮引数 ポインタ仮引数は とする。
ことで,利用者からは
・前者は,そのポインタ引数経由で値を返すことはない。
・後者は,そのポインタ引数経由で値を返す。
という,「その間数の使い方」が明白になる。
また,
・前者は, const T * 仮引数 へは, const T *型の値も T * 型の値も渡せる。これは,T * 型→ const T *型への変換は安全だから許されているからである。
・後者は,
T * 仮引数 へは, T * 型の値は渡すことができるが, const T *型の値は渡せない。これは, const T *型→ T*型への変換はconst性(定数性)が失われ危険なので禁じられているからである。
という違いも出てくる(下図)。
pointerarg.cpp
■配列をポインタ仮引数で受け取る
C言語では,配列をポインタ仮引数で受け取ることが多い。
■文字列引数
以前学習したように,C言語では文字列は char型の配列 で表現されている。そして,項目4
で学習したように,配列は先頭要素へのポインタとして取り扱われる。このため,文字列の
仮引数は,const char * または char * として表現されることが多い。
もちろん,
文字列仮引数は,
・実引数の文字列内容を変更しない場合は const char * とし,
・実引数の文字列内容を変更する場合は char * とする
必要がある。
なお,二重引用符で囲む文字列リテラル定数 ( "東京情報大学" や "こんにちは" )などは,定数
なので,データ型としては const char * である。そのため,文字列リテラル定数を受け取る
ための仮引数は, const char * 型とする必要がある。
stringarg.cpp