3

私が理解できない次のコードについての1つのポインターがあります: function の部分set_array([][9])、コンパイラーが通常の完全な式の代わりにこれを許可する理由set_array([4][9]).ただし、main部分ではint array1[4][9],array1[][9]は許可されていません。

#include <stdio.h>
void set_array(int t_array[][9]);
int main(void) {
    int array1[4][9]; // array1[][9] doesn't allowed

    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 9; j++) {
            array1[i][j] = j + 1;
        }
    }
    set_array(array1);
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 9; j++) {
            printf("%d ", *(*(array1 + i) + j));
            //printf("%d ", array1[i][j]);
        }
        puts("\n");
    }
    return 0;

}
void set_array(int t_array[][9]) {
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 9; j++) {
            t_array[i][j] = 1;
        }
    }   
};

これについての説明はありますか?

4

6 に答える 6

2

関数呼び出し配列では実際にはポインターとして扱われるため、関数定義 t_array[][9]では実際にはそう(*t_array)[9] //pointer to array ですが、配列の宣言では、静的配列を宣言する場合はサイズを明示的に指定する必要があります。これにより、コンパイラーは配列にその量のメモリを割り当てます。したがって、エラーarray1[4][9]ですが、正しいですarray1[][9]. ただし、実行している場合はarray1[][9]、初期化リストを提供する必要があります。

于 2012-10-24T06:57:59.650 に答える
2

比較として (C89):

あなたが書くとき

int a[] 

コンパイラは、「a」に割り当てる必要があるメモリの量を認識していません。このような場合、コンパイラは初期化を使用して配列のサイズを決定する必要があります。

int a[] = {1,2,3}; // sizeof(a)==sizeof(int)*3

書くだけのとき

int a[][9]; 

コンパイラは「a」の大きさがわからないため、適切なメモリを割り当てることができません

引数として配列がある場合

void foo(int a[][9]) 

関数は何も割り当てておらず、'a' を参照しているだけなので、両方の次元の大きさを知る必要はありません。引数から、関数は 'a' を逆参照するときに 'a' を多次元配列 (最初の次元は任意の数値) として扱う必要があることを認識します。

于 2012-10-24T07:02:27.520 に答える
1

Cでは、静的に宣言するときに配列サイズに値を指定する必要があります。そうしないと、コンパイラはその変数に割り当てるメモリの量を認識できません。

配列をarray[][9]として渡す場合、コンパイラは配列に含まれる要素の数ではなく、配列内の要素のサイズのみを知る必要があるため、機能します。したがって、array [] []を引数として渡すことは、コンパイラが格納されている要素のサイズを認識していないため、機能しません。

于 2012-10-24T06:49:17.600 に答える
1

これは、次の 2 つの異なることを行っている場合に発生します。

まず、 という名前の変数を宣言していますarray1。C では、コンパイラーは、そのメモリー量を予約するために宣言しているスペースの量を知る必要があります。したがって、配列の完全なサイズを指定する必要があります。

int array1[4][9];

4 * 9このようにして、コンパイラはint を割り当てる必要があることを認識します。

さて、あなたの関数では、コンパイラは配列のサイズを知る必要はありません (バックグラウンドで配列は関数呼び出しのポインターに変換されます)。要素のサイズを知るだけで済みます。sizet_arrayの要素へのポインタも同様です9 * sizeof(int)。これは、宣言した方法で関数を宣言できるためです。

void set_array(int t_array[][9])

しかし、すべての次元サイズで宣言することも可能です:

void set_array(int t_array[4][9])

しかし、それはコンパイラにとって重要ではありません。

于 2012-10-24T07:07:06.927 に答える
1

初期化リストを使用して、最初の次元を指定せずに宣言および初期化できます。

int array1[][9] = {
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
};

C では、配列をインラインで初期化する場合、2 番目以降は次元のサイズのみを指定する必要があります。コンパイラがインデックスを作成するコードを生成するために必要です。多次元配列 (C の場合) は連続バッファであることを思い出してください。

于 2012-10-24T06:51:50.683 に答える
0

配列に割り当てることはできません。初期化することしかできないため、一度にすべてを行う必要があります。

int array1[4][9] = {
 {1,2,3,4,5,6,7,8,9},
 {1,2,3,4,5,6,7,8,9},
 {1,2,3,4,5,6,7,8,9},
 {1,2,3,4,5,6,7,8,9},
};
于 2012-10-24T06:48:46.007 に答える