1. ホーム
  2. c

[解決済み] C言語のポインタ(宣言と単項演算子)を初心者にどう説明するか?

2022-05-17 18:48:30

質問

最近、C言語プログラミングの初心者にポインタを説明する機会があったのですが、次のような難しさにつまずきました。ポインタの使い方を既に知っている人は全く問題に感じないかもしれませんが、次の例を冷静に見てみてください。

int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);

全くの初心者にとって、この出力は驚くべきものかもしれません。2行目で彼/彼女は *bar を &foo と宣言しましたが、4行目で *bar は &foo ではなく実際に foo であることが判明しました!

この混乱は、* 記号の曖昧さに起因していると言えるかもしれません。2行目ではポインタを宣言するために使用されています。4行目では、ポインタが指す値を取得する単項演算子として使用されています。2つの異なるもの、そうですか?

しかし、このquot;説明"は、初心者の助けには全くなりません。微妙な食い違いを指摘することで、新しい概念を導入しているのです。これでは、正しい教え方とは言えません。

では、カーニガンやリッチーはどのように説明したのでしょうか。

<ブロッククオート

単項演算子 * は、インダイレクトまたはデリファレンス演算子です。ポインタに適用すると、ポインタが指すオブジェクトにアクセスするようになります。[...]

ポインタipの宣言です。 int *ip はニモニックとして意図されたもので、これは式 *ip が intであることを示します。 変数の宣言の構文は、その変数が現れる可能性のある式の構文を模倣しています。 .

int *ip は"のように読みます。 *ipint を返すのでしょうか?しかし、それではなぜ、宣言後の代入はそのパターンに従わないのでしょうか?初心者が変数を初期化したい場合はどうすればいいのでしょうか? int *ip = 1 (読みます。 *ipint と、その int1 を含む)は期待通りに動作しないでしょう。概念モデルが首尾一貫していないように見えるだけです。私はここで何かを見逃しているのでしょうか?


編集する それは にまとめています。 .

どのように解決するのですか?

の意味を理解するために * 記号の意味を理解するためには、まず文脈が実際に異なることを理解する必要があります。いったん文脈が異なることを理解すれば(たとえば、課題の左辺と一般的な表現の違い)、その違いが何であるかを理解するのはそれほど認知的に飛躍したことではありません。

まず、変数の宣言に演算子を含めることができないことを説明します (これを示すために、変数に - または + の記号を変数宣言に使用すると、単にエラーになります)。次に、式(つまり代入の右側)が演算子を含むことができることを示しましょう。式と変数宣言は完全に異なる文脈であることを学生に理解させるようにします。

文脈が異なることを理解させたら、次に * 記号が変数宣言の中で変数識別子の前にある場合、それは「この変数をポインタとして宣言する」ことを意味します。次に、式の中で(単項演算子として)使用する場合は * 記号は「参照解除演算子」であり、以前の意味ではなく「のアドレスの値」を意味することを説明できます。

生徒を本当に納得させるために、C言語の作成者は参照解除演算子を意味する記号を使うことができたと説明してください(つまり、彼らは、参照解除演算子として @ を使うこともできたが、何らかの理由で * .

結局のところ、文脈が違うということを説明しても、どうしようもないのです。文脈が違うことを理解していない生徒は、どうして * 記号が異なるものを意味することができる理由を理解することができません。