すべてのポインターが同じである場合に、ポインターが保持するアドレスを持つデータのタイプを指定する必要があるのはなぜですか。すべてのポインタはアドレスを格納するため。また、ポインタがメモリ内で必要とするスペースの量は、マシンが32ビットか64ビットかによって異なります。
私のポインターptrにintのアドレスが格納されており、マシンが64ビットであるとします。したがって、私のポインターptrの内側に、8バイト(64ビットのアドレス)と言う0x123456789ABCDEF0が表示されます。
Ptrというラベルの付いたボックスがあり、これにintのアドレスであるこの(0x123456789ABCDEF0)noが含まれているとしましょう。さて、このアドレス(0x123456789ABCDEF0)は、そのアドレスがint、char、float、doubleのいずれかであるか、それともRAM内の単なるアドレスであるかを指定していません。では、ptrがポインタであり、そこに含まれるアドレスが(0x123456789ABCDEF0)であると通知されただけで、ポインタがintを指していることを他の誰かがどのように知るのでしょうか。
メモリ割り当ての観点から、あなたは正しいです。 64ビットアーキテクチャーのポインター変数は、それがどのタイプのポインターであっても、8バイトを占めます。
ただし、Cコンパイラは、変数のサイズよりも変数について多くを知る必要があります。類推:long
とfloat
は通常両方とも4バイトが必要です(それで、なぜ異なる型があるのですか???)。しかし、操作の動作は異なります。
ポインタに戻る:ポインタを逆参照するための*
演算子と相対アドレス指定のための[]
インデックス演算子があり、どちらもポインタタイプを知っている必要があります。
int *pi;
と宣言されたポインタの場合、double x = *pi / 2
のようなステートメントは除算を切り捨てますが、float *pf;
を使用すると、float x = *pf / 2
は小数の結果を返します。したがって、いくつかの非常に重要な動作はそのinfoに依存するため、ポインタタイプについてコンパイラに通知する必要があります。
そして、ポインタ演算があります。 []
演算子で行われる相対アドレス指定。私たちが持っている場合
char *pc = 0x12340; // Compiler will complain, as types don't match!
int *pi = 0x12340;
double *pd = 0x12340;
次に、pc[4]
は、0x12340
アドレスの後ろの0x12344
にある4文字を表す文字(バイト)になります。ただし、pd[4]
は0x12344
ではなく、ベースアドレスの32バイト後の0x12360
にあります。ダブルポインターのインデックス付けは、シングルバイトではなく8バイトステップでカウントされるためです。そしてもちろん、これは+
および-
演算子を含むすべてのポインタ演算にも適用されます。したがって、もう一度、正しいポインター演算を可能にするために、ポインター型についてコンパイラーに通知する必要があります。
C言語の重要な機能の1つは、型情報がコンパイラにのみ保持されることです。実行時、メモリ内のpi
ポインタの8バイトには、pi
がint
ポインタであるという情報が含まれていません。異なる型のポインタを操作するための異なるマシンコードを生成するのはコンパイラです。
したがって、値が0x123456789ABCDEF0
のポインタを取得し、他の情報がない場合、それがdouble
、int
、または関数ポインタ(またはその他)であるかどうかはわかりません。 。コンパイルされたコードに「デバッグ」添付ファイルが含まれている場合にのみ、pi
変数がint
ポインターであり、0x123456789ABCDEF0
ポインター値がその値であるという情報が見つかる場合があります変数の場合、int
が指す値を確認するには、0x123456789ABCDEF0
のアドレスから始まる(4バイト?)pi
を探す必要があることがわかります。 。
ただし、このようなデバッグアタッチメントはプログラムの実行に必ずしも必要ではなく、内部を調べたい人のための礼儀にすぎません。