また、遠くと近くのポインタ...誰かが少し詳しく説明できますか?
C ++では、ポインタが直接オペコードレベルまたは回路レベルでどのように機能するかについてはわかりませんが、他のメモリにアクセスするメモリ、またはその逆などはわかっています。
ただし、アセンブリではポインタを使用することもできます。
ここで知っておく価値のある顕著な違いはありますか、それとも同じ概念ですか?低レベルのマイクロプロセッサ固有のアセンブリのニューモニクスレベルでは、異なる方法で適用されますか?
ニアポインタとファーポインタは、16ビットオペレーティングシステムにのみ関連していました。本当に必要でない限り、無視してください。下位互換性のために今日のコンパイラでキーワードを見つけるかもしれませんが、実際には何もしません。16ビット用語では、near
ポインタは16ビットオフセットであり、メモリセグメントはコンテキストによってすでに認識されており、far
ポインタには16ビットセグメントと16ビットオフセットの両方が含まれています。
アセンブラでは、ポインタは単にメモリ位置を指します。同じことがC++にも当てはまりますが、C++ではメモリにオブジェクトが含まれている可能性があります。ポインタの種類によっては、同じオブジェクトであってもアドレスが変わる場合があります。次のことを考慮してください。
class A
{
public:
int a;
};
class B
{
public:
int b;
};
class C : public A, B
{
public:
int c;
};
C obj;
A * pA = &obj;
B * pB = &obj;
pA
等しくなりpB
ません!C
それらはオブジェクトのさまざまな部分を指します。あるタイプから別のタイプにポインターをキャストすると、コンパイラーは自動調整を行います。クラスの内部レイアウトを知っているので、適切なオフセットを計算して適用できます。
一般に、ポインターは、それを指しているため、他の何かにアクセスできるようにするものです。
コンピュータにおいて、「何か」と「それ以外」はメモリの内容です。メモリはそのメモリ アドレスを指定してアクセスされるため、ポインタ (何か) は別の何かのメモリ アドレスを格納するメモリ位置です。
プログラミング言語、高水準またはアセンブラでは、名前はメモリ アドレス (通常は 16 進数で指定される) よりも覚えやすいため、メモリ アドレスに名前を付けます。この名前は、コンパイラー (高レベル) またはアセンブラー (マシン・レベル) の 16 進数とまったく同じ定数の名前、または 16 進数を保管する変数 (メモリー位置) の名前です。
したがって、C++ のような高水準言語とアセンブラーのような低水準言語のポインターの概念に違いはありません。
近く/遠くについて誰もが言ったことに加えて、違いは、C++ ではポインターが型付けされていることです。コンパイラーはポインターが何を指しているかを認識しており、舞台裏でいくつかのアドレス演算を行います。たとえば、int *p
and accessがある場合p[i]
、コンパイラは の値に 4*i を追加p
し、そのアドレスのメモリにアクセスします。これは、(最近のほとんどの OS では) 整数が 4 バイト長であるためです。構造体/クラスへのポインターと同じ - コンパイラーは、構造体内のデータ項目のオフセットを静かに計算し、それに応じてメモリ アドレスを調整します。
アセンブリメモリアクセスでは、そのような運はありません。アセンブリ レベルでは、技術的に言えば、変数データ型の概念はほとんどありません。具体的には、整数とポインターの間に実質的な違いはありません。1 バイトより大きい配列を扱う場合、配列項目の長さを追跡するのはユーザーの責任です。
再近/遠:
これまで、一部のプラットフォーム、特に 16 ビット DOS および 16 ビット Windows では、メモリ セグメントの概念が使用されていました。Near ポインターは想定されるデフォルト セグメントへのポインターであり、基本的には単なるオフセットでしたが、Far ポインターはセグメント部分とオフセット部分の両方を含むため、メモリ内の任意のアドレスを表すことができました。
DOS では、特に C/C++ 用に選択できるさまざまなメモリ モデルがありました。データ セグメントが 1 つしかないため、すべてのデータ ポインターが暗黙的に近くにあり、コード セグメントが 1 つしかないモデルもいくつかありました。コード ポインターとデータ ポインターの両方が遠かったなどです。
セグメントを使用したプログラミングは、実際の PITA です。