5

次のテストアプリケーションがあります。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(void){
    char buf[512];
    buf[0]= 0x1;
    buf[1]= 0x2;
    char *temp1 = &buf;
    char *temp2 = buf;
    char *temp3 = &buf[0];
    printf("temp1:%p, temp2:%p, temp3:%p\n",temp1,temp2,temp3);
    printf("0 = %d, %d, %d\n",temp1[0],temp2[0],temp3[0]);
    printf("1 = %d, %d, %d\n",temp1[1],temp2[1],temp3[1]);
    return;
}

コンパイルすると次の警告が表示されます。

gcc ./testptr.c -o testptr
./testptr.c: In function ‘main’:
./testptr.c:9: warning: initialization from incompatible pointer type

しかし、実行すると、3 つのポインターはすべて同じように動作します。

./testptr
temp1:0x7fff3a85f220, temp2:0x7fff3a85f220, temp3:0x7fff3a85f220
0 = 1, 1, 1
1 = 2, 2, 2

私はそれを知っていますbuf == &buf[0]が、なぜ&buf == &buf[0]ですか?&bufであってはならないchar**?

4

4 に答える 4

3

すべてのポインターが と宣言されているため、すべてのポインターは同じように動作しますchar*。C は静的に型付けされるため、型は値ではなく変数にバインドされます。

振る舞いの部分が説明されたので、(%p printf のように) 実際に同じ値を持っている理由を見つける必要があるだけです。まあ、これは GCC によってメモリ アドレスとして実装されているポインターのアーティファクトです (* を ** とは異なるものにするオフセットとサイジングはすべて、舞台裏の型システム/コンパイラーによって処理されます)。警告を発する最も疑わしいものと同様に、これは未定義の動作であるか、少なくとも悪い習慣である可能性が高いことに注意してください:)

于 2011-10-06T03:00:37.867 に答える
2

配列はポインターではありませんが、ほとんど同じように使用できます。たまたま、配列とポインターのセマンティクスが異なる 1 つの側面を発見しました。

于 2011-10-06T02:49:13.240 に答える
1

*and&演算子の代数から計算できます。

  • 配列bufの 0 番目の要素のアドレスであることがわかっています。buf

  • &buf[0]0番目の要素のアドレスでもあることがわかっています

  • 定義によりbuf[0]*(buf+0)

  • &(*(a))同等aです。

だから、どちらがに&buf[0]なります。&(*(buf+0))buf

アップデート

では、証拠として並べてみましょう。

  1. &buf[0] 与えられた。
  2. &(buf[0])() を使用した C の優先順位規則による
  3. &((*(buf+0)))なぜならbuf[0] == *(buf+0)
  4. &(*(buf+0))不要な括弧を削除
  5. bufQED
于 2011-10-06T02:55:27.157 に答える
1

コンパイラが配列を処理するときに実際にどのようなコードが生成されているかを考えると、より明確になります。名前 buf は、配列の最初 (0 番目) の要素のアドレスを参照します (文字を含むための連続スペース)。「buf」のシンボル テーブルのエントリでオブジェクトを調べると、その最初の要素のアドレスが見つかります。たとえば buf[0] を参照すると、コンパイラは buf のアドレスに char のサイズの 0 を加えたものを生成します。これはたまたま buf 自体のアドレスと同じです。

于 2011-10-06T03:09:28.300 に答える