14

これは C から取られ、それに基づいています。32ビットのポインタがあるとしましょう

char* charPointer;

いくつかのデータを含むメモリ内の場所を指します。このポインタの増分が 1 バイトなどであることがわかっています。一方、

int* intPointer;

また、メモリ内のある場所を指しており、それを増やすと、1 を追加すると 4 バイト増える必要があることがわかります。

問題は、これらのポインターを使用して、完全な 32 ビットのアドレス指定可能スペース (2^32) (4 ギガバイト) をどのようにアドレス指定できるかということchar*ですint*。これにより、32 バイトではなく、それ以下になります。

この質問を入力するとき、私は考えに至りました。おそらく、それはすべてシンタックス シュガーであり、本当にコンパイラーのためのものなのでしょうか? 生のポインターは 32 ビットだけで、型は気にしないのでしょうか? そうですか?

4

6 に答える 6

18

コンパイル時間と実行時間で混乱するかもしれません。

コンパイル中、gcc(または任意の C コンパイラ) はポインターの型を認識します。特に、そのポインター変数が指すデータの型を認識します。したがってgcc、正しいマシンコードを発行できます。したがって、int *変数の増分 (32 ビットを持つ 32 ビット マシン上int) は 4 (バイト) の増分にchar*変換され、変数の増分は 1 の増分に変換されます。

実行時に、コンパイルされた実行可能ファイル (気にも必要もありませんgcc) は、マシン ポインタ、通常はバイト アドレス (またはワードの開始アドレス) のみを処理します。

( Cプログラムの) 型は、実行時に認識されません。

他の一部の言語 (Lisp、Python、Javascript など) では、実行時に型を認識する必要があります。最近の C++ (ただし C ではない) では、一部のオブジェクト (仮想関数を持つオブジェクト) にRTTIがある場合があります。

于 2012-11-16T11:55:46.350 に答える
13

それは確かに構文糖です。次のコード フラグメントを検討してください。

int t[2];
int a = t[1];

2 行目は次と同等です。

int a = *(t + 1); // pointer addition

それ自体は次と同等です:

int a = *(int*)((char*)t + 1 * sizeof(int)); // integer addition

コンパイラは型をチェックした後、キャストを削除し、アドレス、長さ、および整数の加算のみを処理します。

于 2012-11-16T11:55:16.007 に答える
3

あなたの仮説は正しいです。さまざまな種類のポインターがどのように処理されるかを確認するには、次のプログラムを実行してみてください。

int main()
{
    char * pc = 0;
    int * pi = 0;

    printf("%p\n", pc + 1);
    printf("%p\n", pi + 1);

    return 0;
}

char *に1を追加すると、数値が1増加し、int *に4(私のマシンのintのサイズ)が増加したことに注意してください。

于 2012-11-16T11:59:18.780 に答える
3

はい。生のポインターは 32 ビットのデータ (アーキテクチャによっては 16 ビットまたは 64 ビット) であり、他には何も含まれていません。int *それが,char *であるかどうかstruct sockaddr_in *は、コンパイラにとって、インクリメントするときに実際に追加する数を知るための情報と、逆参照するときに持つ型に関する情報にすぎません。

于 2012-11-16T11:55:15.990 に答える
2

最後にあなたが言ったとおりです.Cの型は、変数に対して実行できるさまざまな操作のコードを生成する方法をコンパイラに指示するコンパイル時の概念にすぎません。

最終的に、ポインタはポインタが指し示すアドレスに要約されるだけで、コードがコンパイルされるとセマンティック情報は存在しなくなります。

于 2012-11-16T11:56:11.963 に答える
1

int* ポインターのインクリメントは、ポインター変数が int* として宣言されているという理由だけで、インクリメントする char* とは異なります。int* を char* にキャストすると、1 バイトずつ増加します。

ですから、そうです、それはすべて単なる構文糖衣です。これにより、ある種の配列処理が容易になり、void* ユーザーを混乱させます。

于 2012-11-16T11:54:51.157 に答える