1

私はこれらの2つのステートメントを持っています:

printf("%u",a+1);

printf("%u",(int *)a+1);

実際、この混乱に遭遇したとき、私はこのコードに取り組んでいました。

#include<stdio.h>

int main()
{
  int a[2][2]={1,2,3,4};
  int i,j;
  int *p[] = { (int*)a, (int*)a+1, (int*)a+2 };
  for(i=0; i<2; i++){
    for(j=0; j<2; j++){
      printf("%d %d %d %d",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));
    }
  }
  return 0; 
}

Output:

1 1 1 1
2 2 2 2
2 2 2 2
3 3 3 3

上記のプログラムの出力を理解するために、上記の2つのステートメントの違いを知っていれば、この出力を作成している違いを解決できることがわかりました。

私の現在の理解: (a+1)配列の2番目の要素のアドレスを教えてくれます。この場合、2次元配列は、それぞれ2つの要素を持つ2つの1次元配列として視覚化できます。だから(a+1)私にのアドレスを教えてくれますa[1][0]が、なぜ(int *)a+1私にのアドレスを教えてくれるのa[0][1]ですか?

プログラムの違いと出力について説明してください。

ありがとう。

4

3 に答える 3

3

イディオム(int*)a+1はとして解釈され((int*)a) + 1)ます。つまり、キャストは追加よりも優先されます。したがって(int*) a)、これは、ptr-to-intとしての配列のアドレスであり、1だけオフセットされた、と評価されます。これにより、配列の2番目の要素が返されます(2)。

プログラミングの2つの重要なルール:

ルール1:コードを書くときは、レイアウトに機能を反映させます。
ルール2:コードを読むときは、レイアウトではなく機能を読んでください(当然の結果:コメントではなく、コードをデバッグします。)

概念的には、宣言するとき

int a[2][2]={1,2,3,4};

次のような2次元配列を想定しています。

  1 2
  3 4

しかし、Cは実際には、次のようにデータを連続したメモリブロックに格納します。

  1 2 3 4

インデックスを計算するときに、データが2×2配列を表すことを「覚えています」。しかしa、元の型からにキャストint *すると、コンパイラに元の宣言を忘れるように指示し、事実上2次元性を失い、intsの単純なベクトルになります。

の宣言を理解する方法は次のpとおりです。

int *p[] = { (int*) a,  (int*) a+1,     (int*) a+2 };     // As written
int *p[] = { (int*) a,  ((int*) a) + 1, ((int*) a) + 2 }; // As interpreted
int *p[] = { &a[0][0],  &a[0][1],       &a[1][0] };       // Resulting values

これから、それがpベクトルの1次元配列であることがわかります。

p[0] = { 1, 2, 3 }
p[1] = { 2, 3 }
p[2] = { 3 }

あなたがそれを認識した場合(p+i) == (i+p)、最後の2つの項目は行の最初の2つと同じです

printf("%d %d %d %d\n",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));

これはこれと同等です:

printf("%d %d %d %d\n", p[i+j], p[j+i], p[i+j], p[j+i]);

以下はすべて同等であるため、注意するのは興味深いことです。

a[i]
*(a+i)
*(i+a)

i[a]その場合、同じ値を表すように書くことは完全に合法です。言い換えれば、コンパイラはあなたが書くことを可能にします

printf("%d %d %d %d\n", p[i], i[p], p[1], 1[p]);

もちろん、あなたの技術リーダーはあなたがそれを書くことを許可しないほうがよいです。あなたが私のグループでそれを書くなら、あなたは解雇されます。;-)

于 2012-04-08T12:48:39.733 に答える
2

どちらも未定義の動作を生成します。ポインター値を出力する正しい形式は%p. void*にポインタを送信するときに、ポインタを にキャストしますprintf

于 2012-04-08T12:30:54.863 に答える
0

多次元 C 配列は、互いに隣り合って配置された 1 次元配列のように動作します。したがって、a(通常は(int **)) にキャスト(int *)すると、 から得られるのと同じものが得られa[0]ます。(int *) a + 1です&a[0][1]。_ そうでなければ、あなたの理解は正しいa + 1です&a[1][0]

(この動作は標準で指定されていますが、それは良いプログラミング手法にはなりません。)

于 2012-04-08T12:31:37.597 に答える