3

重複の可能性:
C++ で配列を使用するにはどうすればよいですか?
2次元配列はダブルポインタですか?
二次元配列とポインタ

これは非常に基本的な質問であることは知っていますが、グーグルでこれを解決することはできませんでした。そのため、ここに投稿しています。C ++では、宣言を検討してくださいint x[10];

これは、配列の最初の要素のアドレスを含むベース ポインターである x を持つ 1 次元配列です。だからx私にそのアドレスを*x与え、最初の要素を与えます。

宣言についても同様

 int x[10][20];

ここにある変数の種類x。私がする時

 int **z = x;

コンパイラは、変換できないと言っていますint (*)[20].そしてint **、なぜcout<<x;cout<<*x;が同じ値を与えるのですか?? また、ポインターの配列を次のように宣言した場合

 int *p[10];

xでは、と( タイプに)の違いはありpますか?? 宣言するint x[10]int *p代入が有効になりますxp、2次元配列の場合はそうではありませんか? なぜ?誰かが私のためにこれをクリアするか、これに関する優れたリソース資料を提供してください.

4

3 に答える 3

5

配列とポインタは同じものではありません。C および C++ では、多次元配列は単なる「配列の配列」であり、ポインターは含まれません。

int x[10][20];

それぞれ 20 要素の 10 個の配列の配列です。最初の要素へのポインターに崩壊するコンテキストで使用するxと、それらの 20 要素配列の 1 つへのポインターになりますint (*)[20]。そのようなものはポインターからポインターへのポインターではないため、変換は不可能であることに注意してください。

int *p[10];

は 10 個のポインターの配列なので、x とは異なります。

特に、配列とポインターは同じものだと考えているように見えるため、問題が発生している可能性があります-あなたの質問は次のように述べています:

これは、配列の最初の要素のアドレスを含むベース ポインターである x を持つ 1 次元配列です。したがって、x はそのアドレスを示し、*x は最初の要素を示します。

これは真実ではありません。1次元xは配列です。一部のコンテキストでは、配列が最初の要素へのポインターに崩壊するだけです。

この件について知りたいことはすべてFAQを読んでください。

于 2012-07-16T20:13:16.840 に答える
5

多次元配列は単なるシンタックス シュガーです。舞台裏では、これは単に 10 * 20int秒の長さの一次元配列です。コンパイラで要素にアクセスするとx[5][6]、に相当するものが生成されx[5 * 20 + 6]ます。

于 2012-07-16T20:17:46.923 に答える
2

実際の動作は次のとおりです。コードとコメントを参照してください。

#include <stdio.h>

int x[3][5] =
{
  {  1,  2,  3,  4,  5 },
  {  6,  7,  8,  9, 10 },
  { 11, 12, 13, 14, 15 }
};

int (*pArr35)[3][5] = &x;
// &x is a pointer to an array of 3 arrays of 5 ints.

int (*pArr5a)[5] = x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints.

int (*pArr5b)[5] = &x[0];
// &x[0] is a pointer to 0th element of x,
// x[0] is an array of 5 ints,
// &x[0] is a pointer to an array of 5 ints.

int *pInta = x[0];
// x[0] is 0th element of x,
// x[0] is an array of 5 ints,
// x[0] decays from an array of 5 ints to
// a pointer to an int.

int *pIntb = *x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints,
// *x is an array of 5 ints,
// *x decays from an array of 5 ints to
// a pointer to an int.

int *pIntc = &x[0][0];
// x[0][0] is 0th element of x[0],
// where x[0] is an array of 5 ints,
// x[0][0] is an int,
// &x[0][0] is a pointer to an int.

int main(void)
{
  printf("&x=%p x=%p &x[0]=%p x[0]=%p *x=%p &x[0][0]=%p\n",
         pArr35, pArr5a, pArr5b, pInta, pIntb, pIntc);
  return 0;
}

出力例:

&x=0040805c x=0040805c &x[0]=0040805c x[0]=0040805c *x=0040805c &x[0][0]=0040805c

明示的または暗黙的に 0 のインデックスを使用し、配列が連続しており、配列の最初 (IOW、0 番目) の要素が常に配列の最小アドレスにあるため、結果のポインターはすべて同じ値になります。したがって、3 つの異なるポインター型がありますが、すべて実質的に x[0][0]、つまり 1 に等しい要素を指します。

この配列のポインターへの減衰は、C および C++ の非常に重要な機能ですが、すぐに把握するのは困難です。

配列にポインターを渡すときに、よりコンパクトなコードを記述できます。最初の要素のアドレスを取得する代わりに、配列の名前を記述するだけです。

char str1[] = { 's', 't', 'r', '1', '\0' };
char str2[] = "str2";
printf("%s %s %s %s\n", &str1[0], str1, &str2[0], str2);

出力:

str1 str1 str2 str2

また、クレイジーなこともできます。

int y[3] = { 10, 20, 30 };
printf("%d %d %d %d\n", y[2], *(y+2), *(2+y), 2[y]);

出力:

30 30 30 30

すべては、配列とポインタに関してa[b]は同等だからです。*(a+b)

于 2012-07-16T21:33:03.663 に答える