0

昨日、C で 2 次元配列を動的に割り当てたいという SOに関する質問に出くわしました。

答えの 1 つは、次のように割り当てることでした。

int (*place)[columns] = malloc(rows * sizeof *place);

これは美しいこととは別に、私の頭に疑問を投げかけました。質問は次のとおりです。

以下は、4x4を割り当てるコードです

    int (*arr)[4] = (int (*)[4]) malloc(4 * sizeof *arr);
    printf("%d\n", sizeof arr);                 //Dynamic 2-D array by above method
    
    int **arr1 = (int**) malloc(4 * sizeof(int*));
    for(int i = 0; i < 4; i++)
            arr1[i] = (int *) malloc(sizeof(double));
    printf("%d\n", sizeof arr1);                          //Usual dynamic 2-D array

    int *arr2 = (int*) malloc(4 * sizeof(int));
    printf("%d\n", sizeof arr2);                          //Dynamic 1-D array
    
    

通常の出力は次のとおりです。

4
4
4

sizeof *arrただし、 、sizeof *arr1およびを印刷しようとするとsizeof *arr2、出力は次のようになります。

16
4
4

なぜこれが起こっているのかわかりません。の出力が である理由sizeof *arr16何ですか? 最初のケースでメモリはどのように割り当てられていますか?

また、 と のアドレスを印刷しようとするarr*arr、両方の印刷値が同じになります。*arrは「での値」を意味しますarr。つまり、 arr は独自のアドレスを格納する、つまり、それ自体を指しているということですか (これは可能ではないと思います)。少し混乱しています。どこが間違っているのでしょうか?

ご協力いただきありがとうございます!

4

2 に答える 2

3

ただし、sizeof *arrsizeof *arr1およびsizeof *arr2を印刷しようとすると164、およびが表示され4ます。

どこ:

int (*arr)[4];
int **arr1;
int *arr2;

64 ビット マシンではなく、32 ビット マシンで作業している必要があります。

の型arrは「4 の配列へのポインタint」です。逆参照すると、「4 の配列」が得られますint。に渡されるsizeofと、配列のサイズは 16 ( 4 * sizeof(int)) になります。ほとんどの場合、配列を参照するとき、型は「配列の 0 番目の要素へのポインター」に調整されますが、sizeof()その規則の主な例外です。配列を配列として認識し、配列全体のサイズを返します。

の型arr1は「ポインタへのポインタint」です。逆参照すると、「へのポインター」が得られますint。に渡されるsizeofと、ポインタのサイズは 4 ( sizeof(int *)) になります。

の型arr2は「ポインタへint」です。逆参照すると、int. に渡されるsizeofと、intはサイズ 4 です。


わかった!私はそれのほとんどを手に入れます。しかし...なぜ出力が16にならないのsizeof arr2ですか?

ジェームズがコメントで指摘したように:

は、32 ビット マシンでは 4 にsizeof(arr2)減少するためです。sizeof(int*)

つまりarr2、ポインターです。ポインターのサイズは、32 ビット マシンでは 4 です。

また、arr は「4 int の配列へのポインタ」、つまり単一のポインタです。次に、どうすれば 4×4 行列を取得できますか。

次のいずれかを使用できます。

int mat1[4][4];
int (*mat2)[4][4];

1 つ目は単純な 4×4 行列です。の結果はsizeof(mat1)、32 ビット マシン (およびほとんどの 64 ビット マシン) では 64 になります。

2 番目は の 4×4 行列へのポインタですint。の結果はsizeof(mat2)、32 ビット マシンでは 4 になります。mat2は ( の 4×4 行列へのint) ポインターであるため、サイズ 4 であり、他のすべてのオブジェクト ポインターと同じです (実際には、すべての関数ポインターと同じサイズですが、C 標準ではその関数は保証されません)。ポインターとオブジェクト ポインターは同じサイズですが、POSIX ではそれが保証されています)。

の結果はsizeof(*mat2)を指すオブジェクトのサイズでありmat2、これは の 4×4 行列でintあるため、サイズは再び 64 になります。

于 2012-12-02T16:34:09.587 に答える
1

32 ビット システムでは、各メモリ アドレスを一意に識別するために 4 バイトまたは 32 ビットが必要です。ポインターは、単なるアドレスの所有者ではありません。したがって、4バイトかかります。最初のケースでは、arr は長さ 4 のポインターの配列であるため、4*4 = 16 バイトかかります。他の 2 つのケースでは、arr1 と arr2 は単なる 1 つのポインターです。したがって、4バイトかかります。

于 2012-12-02T16:34:46.753 に答える