3

私はこの質問に答えていましたが、次のコードをテストしたときに混乱しました。

#include <iostream>

using namespace std;

int main()
{
        int **ptr;
        int arr[3][3];
        ptr =(int **) arr;
        for (int i=0;i<3;i++){
                for (int j=0;j<3;j++){
                        cout << &arr[i][j] << " =? ";
                        cout << &(ptr[i][j]) << endl;
                }

        }


        return 0;
}

しかし、私はこの出力を得ます:

0x7fff5700279c =? 0
0x7fff570027a0 =? 0x4
0x7fff570027a4 =? 0x8
0x7fff570027a8 =? 0
0x7fff570027ac =? 0x4
0x7fff570027b0 =? 0x8
0x7fff570027b4 =? 0
0x7fff570027b8 =? 0x4
0x7fff570027bc =? 0x8

なぜそれらは同じではないのですか?

4

3 に答える 3

12
ptr =(int **) arr;

それは非常に悪いことです-それはaを含み、reinterpret_cast未定義の振る舞いをもたらします。2つのタイプ(anint[3][3]とan int**)は、メモリレイアウトの点で完全に互換性がありません。

3行3列の2D配列は、次のような連続したメモリブロックです。

  0,0   0,1   0,2   1,0   1,1   1,2   2,0   2,1   2,2
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘

各ポインターが配列の最初の要素を指す場所へのポインターへのポインターintは、次のようになります。

┌─────┐
│     │ // The int**
└──╂──┘
   ┃
   ▼
┌─────┬─────┬┄
│     │     │   // An array of int*
└──╂──┴──╂──┴┄
   ┃     ┗━━━━━━━━━━┓
   ▼                ▼
┌─────┬─────┬┄   ┌─────┬─────┬┄
│ int │ int │    │ int │ int │    // Arrays of ints
└─────┴─────┴┄   └─────┴─────┴┄
  0,0   0,1        1,0   1,1

これには、2つのレベルの間接参照が含まれます。2D配列型には、通過するポインターの配列がありません。さらに、intこの場合のsの配列int**は必ずしも連続しているとは限りません。

ptr[0]たとえば、いつ行うかを考えてください。式の種類は何ですか?ptrはであるため、int**のタイプはptr[0]ですint*。しかし、実際にはその場所には何がありますptr[0]か?ポインタではありません!代わりに、の配列がありintます。

于 2013-03-23T13:49:31.207 に答える
10

int **ptrと anint arr[3][3]は異なります。

 -----------------------------------
|    C    |         Maths           |
 -----------------------------------
| ptr + 1 | ptr + sizeof(int*)      |
 -----------------------------------
| arr + 1 | arr + 3 * sizeof(int*)  |
 -----------------------------------

したがって、同じ結果はまったく得られません (さらに、同じメモリ表現ptrarr持たない場合もあります)。

int (*ptr)[3] = arr;

の最初の次元のみがarrポインターに減衰するため、機能します。

于 2013-03-23T13:46:25.523 に答える
1

int **は、intへのポインタへのポインタです。これは、ポインタの配列を参照していることを意味します。ただし、int [x] [y]は、サイズがxxyの整数の配列です。これは、y列のx行に配置された単一のメモリブロックです(そのように考える場合。

目的を達成するには、列のアドレスを収集し、それらをint**ポインターの行に格納する必要があります。

int   arry[3][3];
int** ptr = malloc( sizeof(int*) * 3 );

for( int i = 0; i < 3; i++ )
   ptr[i] = arry[i];

for( int i = 0; i < 3; i++ )
    for( int j = 0; j < 3; j++ )
        printf( "%d -> %d\n", arry[i][j], ptr[i][j];

free( ptr );
于 2013-03-23T13:48:05.617 に答える