変数とポインターの違いは何ですか?


10

OOと関数型プログラミングの違いを概説する記事を読んでいた私は、関数ポインターに出くわしました。コンピュータサイエンスの学位(2003年)を修了してからしばらく経っています。そのため、ポインタを調べて記憶を更新しました。

ポインタは、メモリアドレスへの参照を含む変数です。それらは、そのようなデータが存在する場合、そのメモリアドレスに含まれているデータを指すと見なすことができます。または、記事の場合のように、コードのセクションへのエントリポイントを示し、そのコードを呼び出すために使用できます。

なぜこれが変数と異なるのですか?変数はメモリアドレスの記号名であり、コンパイラは名前を実際のアドレスに置き換えます。これは、変数がメモリ位置への参照を含み、そのようなデータが存在する場合、そのアドレスのデータを指すと見なすことができることを意味します。

違いが動作にある場合(おそらく、ポインターを実行時に再割り当てできない、または他の値ではなくシンボリック変数名のみを割り当てることができます)は、それが特定の型の変数、つまりポインター型であることを意味していませんか?同じように、整数型であると宣言された変数は、それが使用できる目的でコンパイルによって制限されます。

ここで何が欠けていますか?


4
特に、ポインタは、実質的には変数の内容がアドレスであることを意味的に解釈する型です。もちろん、2つのアドレスがあり、ポインタのアドレス(つまり、変数が格納されている場所)とポインタが参照するアドレス(変数のアドレスにある実際のデータ)があることに注意してください。ポインタは参照の一種です。
ルーク・マチソン2014

回答:


8

あなたの質問は、いくつかの点で注意深く区別する必要があるため、いくつかの点で興味深いものです。しかし、あなたのビジョンは本質的に正しいように思えます。私はこの回答の大部分を書く前にあなたの参考文献を読んでいないので、私の回答に偏りを与えません。

まず、あなたの声明Variables are symbolic names for memory addresses、それはほぼ正しいですが、概念とその通常の実装を混同しています。変数は実際には、変更可能な値を含むことができる単なるコンテナーです。通常、このコンテナは、アドレスとサイズによって特徴付けられるメモリ空間のブロックとしてコンピュータに実装されます。変数には、多かれ少なかれ情報を含む表現を必要とするオブジェクトが含まれる場合があるためです。

しかし、実装手法とは無関係に、言語のセマンティクスのより抽象的な視点を主に検討します。

したがって、変数は抽象的な観点からは単なるコンテナです。そのようなコンテナは名前を持つ必要はありません。ただし、多くの場合、言語には識別子を関連付けることによって名前が付けられた変数があり、変数の使用を識別子で表すことができます。変数は実際には、さまざまなエイリアスメカニズムを通じて複数の識別子を持つことができます。変数は、より大きな変数のサブパートにすることもできます。例は、配列変数のセルで、配列変数とセルのインデックスを指定して名前を付けることができますが、エイリアスを介して識別子に関連付けることもできます。

技術的に意味的にロードされる可能性のある他の単語を呼び出さないようにするため、やや中立的なコンテナという単語を意図的に使用しています。これは実際には、メモリアドレスと混同されることが多いwilipedia説明されている参照の概念に近いものです。ワードポインタ自体はメモリアドレスとして理解されることがよくありますが、ほとんどの高水準言語を検討する場合には意味がなく、参照するディスカッションペーパーではおそらく不適切です(アドレスは使用できます)。特定の実装を参照します。ただし、Cのような言語には適しています。Cは、実装の概念とマシンアーキテクチャに非常に近いはずです。

実際に、実装レベルで変数または値を見ると、「マシンレベルポインター」の間接的な複雑なシステムがいくつか存在する可能性がありますが、それはユーザーには見えない(そして見えないはずです)ので、抽象的な視点は私は開発することができます。ほとんどのプログラミング言語では、実装は言語によって大きく異なるため、ユーザーは実装について心配したり、知ったりする必要はありません。これは、明示的なバイナリコーディングとほぼ直接関係するアセンブリ言語の高度な代替手段として、機械のアーキテクチャに意図的に近いCなどの一部の言語には当てはまらない場合がありますが、ほとんどの場合、低すぎるレベルで便利に使用できません。状況。

言語のユーザーが知っておく必要があるのは、場合によってはそれよりも少なくなるはずですが、値と関連する操作、それらを含めることができる場所、それらを名前に関連付ける方法、ネーミングシステムが機能する方法、新しい方法定義される値の種類など

612

変化しない値と識別子の関連付けは通常、定数と呼ばれます。その意味で、リテラルは定数です。

「値コンテナ」も値と見なすことができ、識別子との関連付けは、これまで使用してきた通常の「素朴な」意味での変数です。したがって、変数は「コンテナ定数」であると言えます。

識別子と値の関連付け(定数宣言)と変数への値の割り当て、つまり、コンテナ定数として定義されたコンテナに値を格納することの違いは何だろうと思うかもしれません。基本的に、宣言は、構文エンティティである識別子を、意味エンティティであるある値に関連付ける表記法を定義する操作と見なすことができます。割り当ては、状態を変更する、つまりコンテナーの値を変更する純粋なセマンティクス操作です。ある意味で、宣言は、意味論的エンティティに命名(つまり構文)メカニズムを提供する以外は、意味論的影響のないメタ概念です。

実際、代入はプログラムが実行されるときに動的に発生するセマンティック操作ですが、宣言にはより構文的な性質があり、通常、実行とは無関係にプログラムのテキストで解釈されます。これが、静的スコープ(つまり、テキストスコープ)が通常、識別子の意味を理解する自然な方法である理由です。

結局のところ、ポインタ値はコンテナの別の名前であり、ポインタ変数はコンテナ変数です。型システム)。

コードに関して、あなたは述べます [pointers] might indicate the entry point to a section of code and can be used to call that code。実際には、これはまったく真実ではありません。多くの場合、コードのセクションは単独では意味がありません(高レベルまたは実装の観点から)。高レベルの観点から見ると、コードには通常識別子が含まれており、これらの識別子は宣言された静的コンテキストで解釈する必要があります。しかし、本質的には動的(ランタイム)現象である再帰が原因で、同じ静的コンテキストが重複する可能性があり、コードは静的コンテキストの適切な動的インスタンスでのみ実行できます。これは少し複雑ですが、結果として、適切な概念は、コードの一部と識別子が解釈される環境を関連付けるクロージャの概念です。クロージャは適切な意味論的概念です。つまり、適切に定義可能な意味論的値です。次に、クロージャ定数、クロージャ変数、

関数はクロージャーであり、通常、エンティティー(定数および変数)の一部を定義または初期化するためのパラメーターがいくつかあります。

これらのメカニズムの使用に関する多くのバリエーションをスキップしています。

クロージャは、命令型または関数型言語でオブジェクト指向構造を定義するために使用できます。実際、OOスタイルの初期の作業(おそらく名前の前)はそのように行われていました。

あなたが参照した論文は、私がすぐに読み飛ばしたものですが、有能な人が書いた興味深いもののようですが、さまざまな言語とその基礎となる計算モデルについての十分な経験がないと、読みにくいかもしれません。

しかし、覚えておいてください。彼が一貫した見解を保持している限り、多くのものが見る人の目にあります。見方が異なる場合があります。

これはあなたの質問に答えますか?

PS:これは長い答えです。それの一部が不十分だと思われる場合は、それが何であるかを明示してください。ありがとうございました。


私はそれを数回読む必要がありましたが、それは私の質問に答えると思います、はい。私の定義があまりにも実装中心ですが、ポインタは変数の特定のタイプであるという考えが正確であるように思われる、すなわち「ポインタ値は、コンテナのためのちょうど別の名前で、ポインタ変数は、コンテナ変数である」 私はしないでくださいコードブロックのアドレスを含むポインターと、クロージャーを含むコンテナーを含むコンテナーであるという違いがあります。静的コンテキストの違いと実行中のプログラムの違いはありますか?
NectarSoft 2014

1
@NectarSoft違いは、コードのブロックとクロージャの間だけです。私が言っているのは、それ自体、いかなるコンテキストからも分離されているため、コードのブロックは通常何も意味しないということです。「mome rathがborogovesよりも大きい場合、toves outgrabe」と言った場合、これらのすべての概念が定義されているコンテキストを見逃しているため、文は何の意味もありません。この静的コンテキストは通常​​、コードフラグメントを囲むテキストです。問題は、この静的コンテキスト自体が複数のランタイムインスタンスを持つ可能性があり、コードフラグメントはそのうちの1つだけを参照する必要があることです。
バブー2014

1
@NectarSoft(続き)したがって、クロージャ値は、コードフラグメントと、このフラグメントに意味を与える静的コンテキストの動的インスタンスの関連付けです。同じコードフラグメントと同じ静的コンテキストの異なる動的インスタンスとの関連付けは、異なるクロージャを提供します。通常、コードではコンテキストに属する変数を使用できますが、その名前(静的に定義された)は同じままですが、コンテキストの動的インスタンスごとに異なる変数になります。これは問題を明確にしますか、または答えの例を作成する必要がありますか(コメント形式は制約されます)?
バブー2014

問題を明確にしますが、私が考えるのに時間をかける他の質問を持ち出します。たとえば、クロージャーごとに個別のポインターが必要な場合、ポインターは動的コンテキストの一部になり、クロージャー内に属しているようです!また、静的コードブロックに関連付けられ、ポインターによって参照されるこれらの各コンテキストは、必然的にそれ自体のクロージャー内の変数になるため、クロージャー境界とクロージャー階層についても疑問に思います。これはすべてトピック外ですが、私はいくつか読んだり、もう一度行き詰まったときに別の質問をしたりするかもしれません
NectarSoft

@NectarSoft実は。クロージャーを作成するとき、コードに関連付けられたコンテキストを、そのコードに適切な意味を与えるために必要なものに制限しようとします(マイクロ管理情報を回避するためのいくつかの実際的な制約まで)。これは静的に決定できます。
バブー

2

違いは、定義とアプリケーションによって異なります。ポインタは、別の変数のメモリアドレスを保持する特殊な変数です。オブジェクト指向の用語では、ポインタは、変数と呼ばれる一般的なクラスからその動作を継承すると考えられます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.