-2

まず第一に、私は C に自信がありませんが、int の 2D 配列があり、この配列の 1 行のすべての値を書き込む関数が必要です。

例えば:

int main(int argc, char *argv[])
{ 
    int a[2][2];
    a[0][0] = 1;
    a[0][1] = 2;
    a[1][0] = 3;
    a[1][1] = 4;
    change_array(&a[0]);
}

void change_array(int* array[])
{
    (*array)[0] = -1; 
    (*array)[1] = -1;        
}

プログラムはすぐにクラッシュします。change_array 関数を array[0] = -1 に変更しようとしたところ...うまくいきました! 値は正しく変更されます (完全に間違っているはずなので理由はわかりません) が、プログラムの他の部分でこの関数を使用すると、配列の値は変更されません。どのようにそれが可能でしょうか?配列の値を正常に変更するための提案はありますか? どうもありがとうございました!

4

3 に答える 3

2

次のように試すことができます。

#include <stdio.h>

void change_array(int array[2][2])
{
    array[0][0] = -1;
    array[0][1] = -1;
}

int main(int argc, char *argv[])
{
    int a[2][2];
    a[0][0] = 1;
    a[0][1] = 2;
    a[1][0] = 3;
    a[1][1] = 4;
    printf("%d %d\n%d %d\n\n", a[0][0], a[0][1], a[1][0], a[1][1]);
    change_array(a);
    printf("%d %d\n%d %d\n\n", a[0][0], a[0][1], a[1][0], a[1][1]);
}

必要に応じて異なりますが、場合によっては、1 次元配列を使用して 2 次元のゲッター/セッターを構築する方が良いことがわかりました。このような解決策は、この回答で見つけることができます:配列へのポインターの配列を割り当てて解放する正しい方法

于 2013-06-24T12:14:04.257 に答える
0

あなたのコードはchange_array、 に対して宣言されたパラメータとは異なるものを に渡しますchange_array

コードchange_array(&a[0])aは、 は 2 つの配列の 2 つの配列ですint。2つa[0]の最初の配列も同様intです。2 つの最初の配列&a[0]のアドレスも同様ですint。これを の宣言と比較してくださいchange_array。ではvoid change_array(int* array[])arrayへのポインタの配列ですint。だから違うタイプです。

change_array代わりに、で宣言できますvoid change_array(int (*array)[])。次にarray、 の配列へのポインターintであり、コードは ( を使用して(*array)[0] = -1) 動作します。

注: 警告を有効にしてコンパイルする必要があり、できれば厳密な言語セマンティクスまたはペダンティックな言語セマンティクスでコンパイルする必要があります。次に、コンパイラは、事前の宣言なしchange_arrayで使用されていることを警告する必要があります。mainコンパイラが完全な型をchange_array使用前に認識できるように、事前に宣言する必要があります。これにより、コンパイラは間違った型が渡されたことを認識し、警告を発します。

上記でコードは修正されますが、ほとんどの人は別のソリューションを使用します。彼らは で宣言change_arrayvoid change_array(int *array)、 で呼び出しますchange_array(a[0])

ではchange_array(a[0])a[0]は 2 つの の最初の配列ですint。ただし、C 言語には、配列式をその最初の要素へのポインターに変換するという規則があります。だからa[0]自動的に になり&a[0][0]ます。&(この変換は、配列が、sizeof、またはのオペランドではなく、_Alignof配列の初期化に使用される文字列リテラルではない場合に常に発生します。) したがって、呼び出しは へのポインターintであるパラメーターと一致するへのポインターを渡しますint。次に、パラメーターarrayを使用して配列要素にアクセスできるため、 の代わりによりarray[i]単純な構文を使用できます。array[0] = -1(*array)[0] = -1

于 2013-06-24T13:20:01.100 に答える
-3

ではC、配列変数は、パラメーターとして関数に渡されると、配列の最初の要素を含むメモリ アドレスへのポインターに崩壊します。これは、すべての要素が連続したメモリに配置されているという事実に関連しています。したがってC、配列の最初の位置を保存するだけで (次元の数に関係なく)、インデックスに基づいて、アクセスする必要があるポイントされたメモリのオフセットを計算できます。

したがって、コードの特定の部分では、変数aは最初の要素であるa[0][0]. したがって、基本的にこれを行う:

change_array(&a[0]);

おおむね (正確ではありませんが) 以下の場合と同じです:

change_array(a);

さて、C で配列がどのように渡されるかを知っていれば、2 次元配列がパラメーターとして渡されると、最初の座標へのアクセス時に、2 番目の座標の最初の要素がある場所へのポインターが実際に含まれていると推測できるはずです。 . そのarray[0]ため、最初の座標の下にある配列の最初の要素へのポインターを渡しています。そして、*(array[0])実際には2番目の座標の最初の要素にアクセスしています。

ここで追加することも重要です。配列変数はポインターに分解されるため、ポインターを渡すため、C のすべての配列は参照によって渡されます。したがって、渡された配列を変更するすべての関数呼び出しは、実際の変更を行います。

これを知っていれば、関数は次のようになります。

void change_array(int *array)
{
    array[0] = -1;
    array[1] = -1;
}

そして、次のような呼び出しを実行できます。

change_array(a[0]);

の最初の配列の要素を変更するためa

ここで、 での良い実践としてC、またセグメンテーション違反を避けるために、配列のサイズを示す整数であるポインタと共に関数に渡します。

void change_array(int *array, int size);

そして、常にこの境界をチェックするアクセスを実行します。

于 2013-06-24T12:15:24.223 に答える