任意のデータ型のアドレスを保持する必要がある場合は、そのデータ型のポインターが必要です。
しかし、ポインターは単なるアドレスであり、アドレスは常にint
型です。では、なぜデータ型の保持アドレスにはその型のポインターが必要なのでしょうか?
任意のデータ型のアドレスを保持する必要がある場合は、そのデータ型のポインターが必要です。
しかし、ポインターは単なるアドレスであり、アドレスは常にint
型です。では、なぜデータ型の保持アドレスにはその型のポインターが必要なのでしょうか?
いくつかの理由があります:
char
は異なりdouble
ます。C では、「単にポインター」を意味する というポインター型があることに注意してくださいvoid*
。このポインタを使用してメモリ内のアドレスを転送できますが、 が指すメモリ内で操作を実行するには、何かにキャストする必要がありますvoid*
。
ポインタはただではありませんint
。それらは暗黙的にセマンティクスを持っています。
以下にいくつかの例を示します。
p->member
p
タイプが何を指しているかを知っている場合にのみ意味があります。
p = p+1;
ポイントするオブジェクトのサイズに応じて異なる動作をします(実際には、「p」が符号なし整数として見られる場合、それがポイントする型のサイズだけインクリメントされるという意味で)。
「アドレスは常にint型」というあなたの仮定は間違っているからです。
たとえば、何らかの理由で、文字へのポインターが単語へのポインターよりも大きいコンピューター アーキテクチャを作成することは完全に可能です。C がこれを処理します。
また、もちろん、ポインターを逆参照することもできます。その場合、コンパイラーは、問題のアドレスで見つかると予想されるデータの型を知る必要があります。そうしないと、そのデータを処理するための適切な命令を生成できません。
検討:
char *x = malloc(sizeof *x);
*x = 0;
double *y = malloc(sizeof *y);
*y = 0;
これらの 2 つのスニペットは、まったく異なる量のメモリを書き込みます (または、割り当てが失敗した場合は爆発します。今のところ気にしないでください) が、実際のリテラル定数 (0
型int
は ) はどちらの場合も同じです。ポインターの型に関する情報により、コンパイラーは適切なコードを生成できます。
C では型のないポインターを非常に簡単に使用できvoid *
ます。すべてのポインターに対して使用するだけです。私が考えることができる2つの理由から、これはかなりばかげています。
まず、型で指されているデータを指定することにより、コンパイラは多くのばかげた間違い、タイプミスなどからあなたを救います。代わりに、この情報をコンパイラから奪うと、問題になるはずのないものをデバッグするのに多くの時間を費やすことになります。
さらに、おそらく「ポインター演算」を使用したことがあります。たとえば、int *pInt = &someInt; pInt++;
-- これはポインタをメモリ内の次の整数に進めます。これはタイプに関係なく機能し、適切なアドレスに進みますが、コンパイラがポイントされているもののサイズを知っている場合にのみ機能します。
ほとんどの場合、あなたの後にコードを読んで、そのアドレスに何が格納されているかを知ることができます。また、コードでポインター演算を行う場合、データ型のサイズがコンパイル前に知られています。
ポインターの型は、一度に操作を実行できるバイト数をコンパイラーに伝えるためです。
例: の場合char
、1 バイトのみ。また、2 バイトの int の場合は異なる場合があります。