他の記事に触発されて記事を書きました。
C言語を習い始めた1990年頃のこと・・・
以下ような例題がありました。(当時こんな書き方はできなかったはずですが・・・)
#include <stdio.h>
void sub(char c)
{
printf("%c\n", c);
}
int main(void)
{
char message[] = "Hello, world!";
sub(message[0]);
}
ちょっと改造しようと思い、講師に変な質問をしてしまいました:
「sub
関数に "Hello, world!"
の H
を渡したのですから、隣の e
も簡単に取り出して表示できますよね?」と。
引数c
の文字'H'
は "Hello, world!"
の 'H'
なのだから、sub
関数で (&c)[1]
とすれば隣の文字 'e'
を取り出せるんじゃないかと思ってしまったのです。
「なんでできないの?」としばらく思っていました。
変数の値をコピーして引数に渡す(値渡しする) C言語 では無理
実際には、"Hello, world!"
の 文字'H'
のデータをコピーして sub
関数の引数c
に代入されているので、変数c
の文字'H'
から元の"Hello, world!"
の'H'
の位置を特定することはできません。
このような処理を行いたい場合、呼び出し元からデータの位置(アドレス)を渡せばできます。
#include <stdio.h>
void sub(char *c) // *でデータ位置を指し示す(ポイントする)引数になる
{
printf("%c\n", c[0]); // [0] で先頭文字 'H'
printf("%c\n", c[1]); // [1] で隣の文字 'e'
}
int main(void)
{
char message[] = "Hello, world!";
sub(&message[0]); // &でデータ位置(アドレス)を渡す
}
変数領域への参照を引数に渡せる(参照渡しできる) C++言語 なら可能
ちなみに、変数領域への参照を引数に渡せる C++ 言語であれば、私が最初に思ったことを実現できます。
#include <stdio.h>
void sub(char &c) // &で呼び出し元の変数に別名を付けて呼び出し元の変数領域を使う
{
printf("%c\n", c); // 変数cは普通のchar型変数として扱える
printf("%c\n", (&c)[1]); // 変数cのアドレスは呼出し元変数のアドレスなので次の文字を取り出せる
}
int main(void)
{
char message[] = "Hello, world!";
sub(message[0]);
}
H
e
さいごに
講師の方々、いろいろ間違った理解をする受講生がいますので、温かいサポートをお願いします。(自戒も含めて)