はてなキーワード: メモリアとは
ポインタ、参照(リファレンス)、束縛(バインディング)、それぞれ似てるけど同様に語ると混乱の元ではないかと。
ポインタはメモリアドレスに型情報をくっつけたもの。加減算できる点が特徴で、それはメモリアドレスの概念由来だろう。
変数というメモリ上の記憶域を指すフィジカルに近い概念で、配列の運用(*p++で回すとか)、引数の参照渡し(コピー抑止、複数戻り値の実現)、メモリそのものの管理(malloc)あたりで、基本手作業による最適化のための仕組みという側面が近いと思う。
perlだと、変数はやっぱり記憶域ではあるけれど概念として一段抽象化されていて、メモリという連続した領域じゃなく独立した領域の集合となっているから、リファレンスの加減算はなし。
また、配列も単なるメモリの並びからより抽象化してリストもできたから、配列運用や複数戻り値もリストがあるのでリファレンスに頼ることはなくなる。
ただ、オブジェクトの概念があって、オブジェクトをオブジェクトとして入れる変数は用意せずリファレンスとすることで、文法上の変数の型を増やさない、コピー時のコンストラクタの問題を回避するなどのほか、オブジェクトの概念を援用して無名関数や無名変数、ファイルハンドルなども変数=引数として扱えるようにした。
で、pythonはもう一段推し進めて、今までの数値や文字、配列もオブジェクトとみなし、変数はすべてオブジェクトを指し示すもので、記憶域は変数としてあるのではなくオブジェクトとしてあり、変数にリファレンスという特別なものがあるのではなくなり、変数は記憶域をもっていて値が代入されるものではなく、既にあるオブジェクトに変数名という名前(ラベル)を付けて束縛する行為とされる。
見方を変えると変数はすべてにおいてリファレンスで、代入とは値そのものの代入でなく値へのリファレンスの代入で、引数も参照渡しであるが、引数に代入したところでリファレンスが変わるだけで元の値が変わるわけではなく、しかし他の演算などでは自動的にデリファレンスされており、単純な数値や文字列など、自身を変更する機構を持たない(できない)ものにとっては実質的に今までとの違いはないに等しい。隠ぺいといえば隠ぺいか。
java, javascript, rubyもおおむねこの考え方でよかったと思う。
ただ、phpは若干両者が混じったところがあって微妙なところがある。
参考
残念ながら、その読書履歴だと、ここで言う「原理」には辿り着いてないと思います。挙げられた本はどれも計算に関する抽象概念からさらに上の、アーキテクチャを言語化する部分に関してです。それらも原理と言えば原理なのですが、そこからスタートしてもC言語でのプログラムは書けるようになりません (Rとかなら書けるかもですが)。
ここで言う『原理』すなわち、なぜ char x[sizeof(int)]; がダメなのか、という理解につながる原理は、「レジスタ」「ALU(CPUの中の計算ユニット)」「バス」「メモリ」といった原理です。メモリアクセスやヒープ・スタックの使い方、アセンブラといったような話です。
なんで言語の約束事の上っ面を覚えるのが難しいか、というと、「原理」を理解していないからなんです。原理を理解せずに約束事だけ覚えたって使えません。曖昧で良いので、プログラムを動かしているときにどのようにメモリが構成されどのようにアクセスされるのかを知る努力をして下さい。その上でC言語をよく見ると、いかにCPUアーキテクチャに近い所で記述されているのかがわかるようになると思います(*)。
それだけで、目の前の箱がどう動いているかの理解度が劇的に上がる筈です。
*: 理解したつもりになるだけですが、現実のコンパイラもCPUも、そのさらに7歩ぐらい先に行っています。ですが、この領域は進めば進むほど泥沼なので、「あ、Cって高級アセンブラなんだな」という所で実用上は十分だと思います。てか、偉そうなこと言っている私(某大学博士課程在籍、要は増田で現実逃避中のダメ学生)も、そこから先はちゃんと理解していません…。