3

以下のコードからの質問:

#include <stdio.h>

int main(int argc,char *arg[]){

    if (argc>2){
      int m=atoi(arg[1]);
      int n=atoi(arg[2]);

      int a[m][n];
      int (*p)[m][n]=&a;

      printf("p : %p, *p : %p, **p : %p\n",p,*p,**p);
    }

    return 0;
}

メイン環境: gcc バージョン 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) x86-64

gcc main.c
./a.out 2 4

出力:

p : 0xbfea7ef0, *p : 0xbfea7ef0, **p : 0xbfea7ef0

質問はなぜですかp == *p == **paこれは、アドレスが特定のものである配列、一種の定数ポインターであり、これにはgccの実装の詳細が含まれているためだと思います。

4

2 に答える 2

6

p次元を持つ配列へのポインタ[m][n]です。そのポインタの値は のアドレスなaので、印刷pすると のアドレスが得られますa

*p次元の配列[m][n]です。ポインターとしての this の「値」は、配列の最初の要素へのポインターですa[0]。と同じ住所aです。

**p次元の配列[n]です。このポインターの値は、配列の最初の要素へのポインターですa[0][0]。これもまた同じ住所aです。

于 2013-04-09T02:47:50.733 に答える
1

観測された動作は、固定サイズの配列と可変的に変更された配列で同じです。

#include <stdio.h>

int main(void)
{
    enum { m = 3, n = 4 };
    int a[m][n];
    int (*p)[m][n] = &a;

    printf("p : %p, *p : %p, **p : %p\n", p, *p, **p);
    return(0);
}

私のマシンでは、これにより次のものが生成されました。

p : 0x7fff6c542520, *p : 0x7fff6c542520, **p : 0x7fff6c542520

もちろん、pは両方のプログラムの 2D 配列へのポインターです (また、「両方のプログラムで」修飾子は適用されますが、再度追加するつもりはありません)。を印刷pすると、それに割り当てられている配列のアドレスが得られます。これは のアドレスですapは 2D 配列へのポインターであるため、2D 配列は' *pis' ですが、ほとんどの場合、配列参照は最初の要素へのポインターになるため、参照と同じメモリ位置である*pへのポインターになります。同様に'is' は 1D 配列ですが、同様にへのポインタであり、参照と同じメモリ位置でもあります。したがって、3 つの値は同じであるはずであり、コンパイラはそれを正しく取得します。a[0]a**p**pa[0][0]a

それは簡単に読めるものではありませんが、説明しようとしているのは C でもありません。

p以下は、*pとが指すさまざまなオブジェクトのサイズを示す元のプログラムのマイナー バリエーションです**p

#include <stdio.h>

int main(void)
{
    enum { m = 3, n = 4 };

    int a[m][n];
    int (*p)[m][n]=&a;

    printf("p+0 : %p, (*p)+0 : %p, (**p) + 0 : %p\n",
           (void *)(p+0), (void *)((*p)+0), (void *)((**p)+0));
    printf("p+1 : %p, (*p)+1 : %p, (**p) + 1 : %p\n",
           (void *)(p+1), (void *)((*p)+1), (void *)((**p)+1));
    return(0);
}

厳密には、%p変換指定にはvoid *;を指定する必要があります。ここのキャストはそれを強制します。元のコードは公式には少しずさんですが、問題になるマシンはほとんどありません。

これからの出力は次のとおりです。

p+0 : 0x7fff63453520, (*p)+0 : 0x7fff63453520, (**p) + 0 : 0x7fff63453520
p+1 : 0x7fff63453550, (*p)+1 : 0x7fff63453530, (**p) + 1 : 0x7fff63453524

+1バージョンで表されるように、指しているオブジェクトのサイズがどのように異なるかに注意してください。

sizeof(*p)   = 0x30
sizeof(**p)  = 0x10
sizeof(***p) = 0x04
于 2013-04-09T02:28:40.493 に答える