4

これは、「C で配列を動的に割り当てる方法」について先生が教えてくれたサンプル コードです。しかし、私はこれを完全には理解していません。コードは次のとおりです。

int k;
int** test;
printf("Enter a value for k: ");
scanf("%d", &k);
test = (int **)malloc(k * sizeof(int*));
for (i = 0; i < k; i++) {
    test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values
}

C で配列を定義するには[]、名前の後にを付ける必要があると考えましたint** test。単なるポインターへのポインターではありませんか?そして、そのmalloc()線も私を本当に混乱させます.....

4

7 に答える 7

17

宣言 によるとint** test;testポインターへのポインターであり、コード pice は、malloc 関数を使用して動的に int 値のマトリックスにメモリを割り当てます。

声明:

test = (int **)malloc(k * sizeof(int*));
    //                ^^------^^-------
    //  allocate for  k  int*  values    

k int ( ) へのポインタに継続メモリを割り当てint*ます。したがって、k = 4次のようなものが得られたとします。

 temp      343  347  351  355
+----+    +----+----+----+----+
|343 |---►| ?  | ?  | ?  |  ? |
+----+    +----+----+----+----+

アドレスは 4 バイトであり、?ガベージ値を意味すると想定しています。

temp変数に割り当てられた変数は、malloc によって返されたアドレスを割り当てます。malloc は、サイズ = のメモリ ブロックを割り当て続けます =k * sizeof(int**)私の例では = 16 バイトです。

for ループでは、kint にメモリを割り当て、返されたアドレスをtemp[i](以前に割り当てられた配列の場所) に割り当てます。

test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values
//                     ^^-----^^----------
//       allocate for  k   int  values    

注: 式temp[i]== *(temp + i). したがって、各反復の for ループでは、次のような k int 値の配列にメモリを割り当てます。

   First malloc                     For loop   
  ---------------                  ------------------
       temp
      +-----+
      | 343 |--+
      +-----+  |
               ▼                    201   205   209    213  
        +--------+                +-----+-----+-----+-----+
 343    |        |= *(temp + 0)   |  ?  |  ?  |  ?  | ?   |  //for i = 0
        |temp[0] |-------|        +-----+-----+-----+-----+
        | 201    |       +-----------▲
        +--------+                  502   506  510    514
        |        |                +-----+-----+-----+-----+
 347    |temp[1] |= *(temp + 1)   |  ?  |  ?  |  ?  | ?   |  //for i = 1
        | 502    |-------|        +-----+-----+-----+-----+
        +--------+       +-----------▲
        |        |                  43    48    52    56
 351    | 43     |                +-----+-----+-----+-----+
        |temp[2] |= *(temp + 2)   |  ?  |  ?  |  ?  | ?   |  //for i = 2
        |        |-------|        +-----+-----+-----+-----+
        +--------+       +-----------▲
 355    |        |
        | 9002   |                 9002  9006   9010 9014
        |temp[3] |                +-----+-----+-----+-----+
        |        |= *(temp + 3)   |  ?  |  ?  |  ?  | ?   |  //for i = 3
        +--------+       |        +-----+-----+-----+-----+
                         +-----------▲

繰り返し?ますが、ガベージ値を意味します。

追加のポイント:

1) 返されたアドレスを malloc でキャストしていますが、C では避ける必要があります。malloc の結果をキャストしますか?を参照してください。次のようにしてください:

test = malloc(k* sizeof(int*));
for (i = 0; i < k; i++){
    test[i] = malloc(k * sizeof(int));
}

2)メモリを動的に割り当てている場合は、作業が完了したときにメモリを明示的に解放する必要があります(動的に割り当てられたメモリを解放した後は、そのメモリにアクセスできません)。メモリを解放する手順testは次のとおりです。

for (i = 0; i < k; i++){
    free(test[i]);
}
free(test);

3) これは、2D マトリックスにメモリを配列の配列として割り当てる 1 つの方法です。すべての配列に完全に継続してメモリを割り当てたい場合は、この回答を確認してください:関数 C でメモリ 2 次元配列を割り当てる

4) 説明が役に立ち、3D 割り当てについて学習したい場合は、この回答を確認してください:文字列または/ 3D char 配列の行列

于 2013-10-08T06:48:00.867 に答える
2

すべての型 T には、型「T へのポインター」が存在します。

変数は、*型宣言子を使用して、さまざまな型の値へのポインターとして宣言できます。変数をポインターとして宣言するには、その名前の前にアスタリスクを付けます。

したがって、「すべての型 T に対して」は、char** や int*** などの複数間接ポインターが存在するポインター型にも適用されます。「配列へのポインター」型も存在しますが、「ポインターの配列」ほど一般的ではありません ( http://en.wikipedia.org/wiki/C_data_types ) 。

したがって、int**テストは「int配列」を指すポインターの配列を宣言します

test = (int **)malloc(k*sizeof(int*));の k 個の ( int*)に十分なメモリを確保します。

そのため、それぞれが指すポインタがk個あります...

test[i] = (int*)malloc(k * sizeof(int)); (各ポインターは、整数の k 量のサイズの配列を指します)

概要...

int** test;それぞれが k 量の int を指す k 量のポインターで構成されます。

于 2013-10-08T06:45:55.140 に答える
2

malloc は、テスト変数にメモリを動的に割り当てるために使用されます。* を配列、** を配列の配列と見なしますが、値を渡すのではなく、ポインタを使用して変数のメモリ アドレスを参照します。malloc が呼び出されると、整数のサイズを取得し、ユーザーが指定する整数の数を掛けることによって、メモリをテスト変数に割り当てます。これは、ユーザーがこれを入力する前にわからないためです。

于 2013-10-08T06:28:16.113 に答える
2

はい、まったく問題ありません。testはポインタへのポインタなのでtest[i]、書き込みと同等のものはtest + iポインタになります。理解を深めるために、このc-FAQをご覧ください。

于 2013-10-08T06:28:51.620 に答える
1

int** は int のポインタへのポインタです。「左右」のルールを見てみましょう

于 2013-10-08T06:29:27.480 に答える