わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

ポインタ変数,配列変数

ポインタとは何なのか,ということを考えるときに,まず一番最初にはっきりさせておかなければならないのは,「“ポインタ”と“ポインタ変数”は,まったく別のものである」ということです.これは「整数」と「整数型の変数」がまったく別のものであるということと同じです.
(プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み, p.105)

ポインタという概念に慣れるまでのあいだは,混乱を避けるために,ポインタ変数を「ポインタ」と呼ぶのはやめて,あくまでも「ポインタ変数」と呼ぶことをお勧めします.
(同上)

上の2点,賛成です.しかし,気になることもあります.
これらは,pp.104-106のコラムの中で書かれているのですが,このコラムの見出しが「配列,アドレス,ポインタ,ポインタ変数」となっています.本を通じて,「配列変数」という表現がありません.
私の授業で,とりわけポインタ変数と区別させるために多用している「配列変数」は,この本では「配列」としており,私の授業での(いわば総称としての)「配列」も,同じ表記となります.別の言い方をすると,この本を読んで「配列」と書かれていれば,一つ一つ,しくみ*1なのか変数なのかを,確認しないといけません*2
ほぼ同時期に買った本でも,C言語の説明の中では,「配列変数」を使用していません.例えば:

リスト4-2と図4-2を見てください.ここではまず5〜6行目でint型の配列arrayと,int型を指すポインタ変数pを定義しています.
(JavaプログラマのためのC作法 虎の巻, p.75)

なぜ「配列変数」と呼ばないかについては,少し前のページに,示唆する情報がありました.

じつはCでは,配列名への代入は許されていません.(厳密には少し違うのですが)Cの配列名※5は定数だと思っておけば,ほぼ間違いありません.定数ですから代入ができなかったわけです.
(p.59)

※5 Cの配列名
正確には「配列型の式」です.配列型の式の代表的なものが配列名です.
(p.58)

ところで「ポインタ変数」を使用し,一方で「配列変数」という表現を避けるのは,K&Rの影響かなと考えます.手持ちの本はANSI対応版で,最初のものは目を通したことがないのですが,関係するところを引いてみます.

A pointer is a variable that contains the address of a variable. Pointers are much used in C, partly because they are sometimes the only way to express a computation, and partly because they usually lead to more compact and efficient code than can be obtained in other ways. Pointers and arrays are closely related; this chapter also explores this relationship and shows how to exploit it.
(C Programming Language (Prentice Hall Software), p.93)

There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.
(同上,p.99)

このように読み比べつつも,自分の授業では今後も「配列変数」「ポインタ変数」を使用していきます.ともに変数として宣言できるからです.例えば:

char str[] = "abc", *p = str;

この例を使って,p++ができてstr++ができないのは,strが変数でないから(定数だから)ではなく,変更可能な左辺値ではないから,と考えます.ただし授業では「左辺値」は教えるものの,「変更可能な左辺値」までは説明していません*3.str++はできないけれどstr[0]++はできることも,合わせて説明しないといけませんね.
それと,関数の仮引数で配列形式で宣言しても,ポインタ変数となることについても,そこだけ「配列名」と書くよりは,「仮引数は一つ一つ変数である.ただし,配列変数として宣言しているときは,その配列型と適合する*4ポインタ変数になる」と考えるほうが,すっきりします.
授業では,算術型,制御文,演算子までを教えたところで,「第2段階」として,配列を扱います.配列は要素一つ一つを変数のように扱える*5のですが,それらを「オブジェクト」と呼びます*6.次はポインタで,&演算子や,配列とポインタの関係などを説明したのち,1コマ使って文字列処理のプログラム例を提示します.それから関数を取り上げます.値渡しだとかポインタ渡しだとか,関数の中で宣言する配列の扱いだとかも重要ですが,ここで「変数の有効範囲」と「オブジェクトの生存期間」の違い,あるいはもっと端的に「変数」と「オブジェクト」の違い*7を理解させることも不可欠と考えています.関数の再帰呼び出しの中で,同じ有効範囲なのに別々にオブジェクトが作られ,消滅する(使用不可になる)過程を説明します.ちなみに第2段階の最後は,ライブラリ関数です.
最後に…

また,用語としての「ポインタ」も,文脈によってさまざまな意味で使われます.

  • ポインタ変数
  • ポインタ値
  • ポインタ型
  • 以上のものを扱うための仕組み全体の意

本書ではこれらをきちんと区別してそれぞれの用語を使うようにしていますが,世間的には(文脈によって判断しなさい,と)「ポインタ」とだけ呼ばれることが多いので注意が必要です.
(JavaプログラマのためのC作法 虎の巻,p.70)

これもコラムの中からで,内容には賛同なのですが,自分の授業でも使用している「ポインタ値」という表現について,これを誰がどこで使い出したのか,気になっています.

*1:『配列は,1種類の型のデータを複数まとめて扱うしくみです』,同書p.84

*2:p.85の本文と注釈にある「char型の配列」は,どちらでしょうか?

*3:C言語によるプログラミング―スーパーリファレンス編,p.149

*4:この表現は適切でないので,よりよい表現を検討することにします.とりあえず本日はこの表現で,ご容赦ください.

*5:多次元配列とかは別として.

*6:int型の変数名も,ポインタ変数も,オブジェクトではないのですが.

*7:コンパイラが知っている情報」と「実行時のメモリの状態」の違い,とも言えます.