2016-11-10 21 views
0

1週間前にC言語の学習を始めました。 テストのために、私はtictactoeゲームを書くことに決めました。2次元配列をC言語の関数に渡す方法

私にはフィールドがあります。

int field[3][3]; 

そして

void printField(int field[3][3]){ 
for(int i = 0; i < 3; i++){ 
    for(int j = 0; j < 3; j++){ 
     printf("%i", field[i][j]); 
    } 
    printf("\n"); 
}} 

をprintField機能それは、このようにメインで働いています:

int main(){ 
printField(field);} 

しかし、私は

void printField(int field){...} 

または

を変更した場合
void printField(int field[][]){...} 

それは私にエラーの束を与える:

subscripted value is neither array nor pointer nor vector      
passing argument 1 of ‘printField’ makes integer from pointer without a cast 
note: expected ‘int’ but argument is of type ‘int (*)[3]’ 

私はこのような配列を渡すことができないのはなぜ? これ以上の方法はありますか?

+0

よく 'int'は' int'変数を単一の 'int'変数として宣言します。それは明らかに間違っています。単一の整数は配列ではなく、配列の配列ではありません。そして、 'int field [] []'は単純に許可されていません。エラーメッセージに示されているように、あなたが働いている方法か 'int(* field)[3]'か、 。 –

+0

配列はポインタとして渡されるので、実際の番号を送信せずに番号を指す(配列内の最初のもの)ため、 'int field'は機能しません。 int * field、int field []はcと同じですが、2番目の構文はコードの可読性のための砂糖です。 – kabanus

+0

私は理解したように、フィールドを再利用可能にする方法はありません。すでに宣言していてサイズはprintField()でもう一度渡す必要がありますか? –

答えて

2

機能はへの呼び出しとは無関係です関数。したがって、関数は残りのプログラムから配列の大きさを推測することはできません。関数本体には、すべての次元を表す定数または変数が必要です。

void printField(int r, int c, int field[r][c]) 
{ 
    for(int i = 0; i < r; i++) 
     for(int j = 0; j < c; j++) 
      printf("%i", field[i][j]); 

    printf("\n"); 
} 

をAND関数を呼び出すために:

あなたはこの代わりの固定サイズのための変数を使用することができ

printField(3, 3, field); 

あなたは、配列の名前から寸法を計算することができます。マクロを使用すると、醜い構文が閉じ込められます。

#define printField(a) printField(sizeof(a)/sizeof((a)[0]), sizeof((a)[0])/sizeof((a)[0][0]), (a)) 

int f1[3][3] = { 0 }; 
printField(f1); 

int f2[4][5] = { 0 }; 
printField(f2); 
+0

Thanx you!私はこのトリックを探していました –

0

関数として配列を書くと、コンパイラはその配列を静かに「調整」し、最初の要素へのポインタで置き換えます。したがって、void func (int x[3])と書くと、コンパイラは暗黙にこれをvoid func (int* x)に置き換えます。ポインタは配列の最初の項目を指します。

Cがこのように設計されている理由は、大きな配列がスタックにプッシュされることを避けるものではなく、遅くてメモリを消費します。あなたのケースで

、機能void printField(int field[3][3])は静かint[3]配列である第一要素を指し配列ポインタある

void printField(int (*field)[3]) 

に行の後ろに調整します。これはまだfield[i][j]として使用することができるので、すべてうまくいきます。あなたはそれが関数内の配列であるとふりまとうことができます。


void printField(int field)明らかに意味をなさない。これは配列ではなく、単一の項目です。普通のintに[]を使用することはできません。コンパイラがあなたに言っているのは、 "添え字付きの値は配列でもポインタでもベクトルでもありません"。


void printField(int field[][]){...}[]手段「は不完全型の配列を宣言」するので、いずれかの動作しません。配列サイズが定義される前には使用できません。

void printField(int field[])の場合には、前述の「配列調整」機能のためにこのようなことが起こります。コンパイラは配列のサイズを知る必要はありません。なぜなら、配列をint*と置き換えるだけなのでです。

しかし、2つの未知の次元がある場合、コンパイラはint field[][]int (*field)[]に調整しようとします。これは不完全な型の配列へのポインタであり、関数では使用できません。

ただし、int field[][3]を実行しても問題ありません。

+0

しかし、私はすでにintフィールド[3] [3]を宣言しました。なぜ私はそれをもう一度サイズで渡さなければならないのですか?フィールドサイズを変更する場合はどうすればよいですか? –

+0

@関数の宣言と定義が一致している必要があります。可変サイズが必要な場合は、関数を 'void printField(int x、int y、int field [x] [y]) 'として宣言する必要があります。 – Lundin

+0

あなたは@Lundinです。それが私が探していたものです。 –

-4

Cであなたが静的配列で動作するよりも、それはpointeurで動作するように多くの方が良いでしょう。この

void printField(int **field){...}

ようにあなたの配列を渡すことができます:)

+0

ええ、それは実際に私が探していたものですが、mainでprintField(フィールド)をどのような型にキャストすべきですか? –

関連する問題