0

知りたかったのですが、これは関数内で参照によって 2 次元配列へのポインターを渡す正しい方法ですか?

bool test::testTheNumber(test (*arr)[9][9], int testNumber, int row, int column)
{
    if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
     ....
}

私の「theRow」と「theColumn」の答えは、テスト関数に非常に似ています。

bool sodoku::theRow(sodoku (*arr)[9][9], int testNumber, int row)

bool sodoku::theColumn(sodoku (*arr)[9][9], int testNumber, int column)

私の main.cpp には、2 次元配列へのポインターがあり、次のように関数を呼び出しました。

test *arr[9][9];
theRow(arr,0,0);
theColumn(arr,0,0);
testTheNumber(arr,0,0,0,0);

配列は参照渡しですか、それとも * の代わりに & を使用する必要がありますか? 2次元配列がどのように機能するか完全にはわからないので、少し混乱しています。

ありがとう。

4

3 に答える 3

2

C配列は非常に混乱しており、C ++はCと互換性があるという混乱を継承しています。配列がどのように機能するかを理解するための基本は、次のとおりです。

1)配列変数は、式内で最初の要素へのポインターとして動作しますが、定数であり(つまり、「array = p;」は実行できません)、sizeof(array)は配列のサイズ(1要素のサイズ× sizeof(pointer)はポインタのサイズを示しますが、要素の数)。

int array[5];
int* p = array;

その場合、次の式が真になります。

array[0] == *array
sizeof(array) == sizeof(int)*5
sizeof(p) == sizeof(void*)

2)関数の引数を配列として定義すると、常に最初の要素へのポインターとして渡されます。そして、そのように機能で動作します。実際、Cはその場合、渡された配列のサイズを無視します。さらに、関数内で引数を配列または配列の要素へのポインターとして定義することは、コンパイラーによって同じであると見なされます。それで:

void func(int array[5]);
void func(int array[]);
void func(int *array);

まったく同じ関数を宣言し、この関数内でsizeof(array)== sizeof(void *)

そのため、配列は常に参照によって渡され、最初の要素へのポインタのように見えます。

現在、多次元配列は、実際には、要素が配列である1次元配列です。それについてのC/C ++の紛らわしい部分は、C /C++が一般的に型を定​​義する紛らわしい方法です。それで:

test* array[9][9];

C / C ++型を読み取るには、識別子から開始し、[]と()が優先されるため、arrayは9要素の配列(最初の[9])であり、9要素の配列(2番目の[9])であることに注意してください。これは「test」タイプへのポインタです。

ここで、このメソッドのarr引数について:

bool sodoku::theRow(test (*arr)[9][9], int testNumber, int row)

arrは、9つの「テスト」要素の9つの配列の配列へのポインター(括弧は優先順位を変更します)です。

これは、上記の前の「array」変数とは大きく異なります。特に、「array」には「test」へのポインタが含まれ、arrには「test」要素が含まれるためです。

ところで、次の宣言は完全に同じです。

bool sodoku::theRow(test arr[][9][9], int testNumber, int row)

「arr」は、9つの「test」への9つの配列の配列の最初の要素へのポインタとして解釈することもできます。

実際には、おそらくやりたいことは、「テスト」の9つの配列の配列を渡すことです。

boot sudoku::theRow(test arr[][9], int testNumber, int row)
{ ... }

test array[9][9];
sudoku::theRow(array, 0, 0);

また、このメソッドは次のように定義することもできます。

boot sudoku::theRow(test (*arr)[9], int testNumber, int row)
{ ... }

C / C ++のこの非常に紛らわしい配列/ポインターの取り違えについて、インターネット上に多くの情報が存在します。例:http: //pw1.netcom.com/~tjensen/ptr/pointers.htm

于 2012-10-14T01:42:30.763 に答える
2

これ

bool test::testTheNumber(test (*arr)[9], int testNumber, int row, int column)
{
    if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
     ....
}

または

bool test::testTheNumber(test arr[][9], int testNumber, int row, int column)
{
    if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
     ....
}

配列の最初の次元は必要ありません。

実際、配列はデフォルトで参照によって渡されます。は必要ありません&

詳細については、この質問に対するこの回答をお読みください。

于 2012-10-14T00:38:20.383 に答える
0
bool test::testTheNumber(test (*arr)[9][9], int testNumber, int row, int column)

これは、関数内で参照によって 2 次元配列へのポインターを渡す正しい方法ですか?

技術的には、これは配列を参照渡しするのではなく、配列へのポインタを値渡しします。それ以外の場合、セマンティクスは非常に似ています。9x9 整数の配列を参照によって関数に渡す場合、シグネチャは次のようになります。

bool test::testTheNumber(test (&arr)[9][9], int testNumber, int row, int column)

*唯一の違いは、 (ポインター) を&(参照)に変更していることに注意してください。これを使用すると、次のようになります。

int main() {
   test array[9][9];
   test t;
   t.testTheNumber(array,1,2,3);
}

(これが意味をなすかどうかは、まったく別のことです...たとえば、メンバー関数ではなく非メンバー関数を提供したい場合があります)

Geoff の提案はどちらも同等であり、インターフェイスを変更する際に配列のサイズが署名で固定されないという問題があります。つまり、関数は 9x9 の配列を受け取りますが、2x9、3x9...Nx9 の配列も受け入れます。

bool f(int (*arr)[9]);
int main() {
    int array[9][9];
    f(array);          // ok, but so is:
    int array2[3][9];
    f(array2);
}

ご覧のとおり、関数の引数の型を変更することにより、最初の次元が解放され、コンパイラはそこで任意のサイズを喜んで受け入れるようになるため、元のオプションよりも悪いオプションになります。

最後に、私の提案は、9x9 マトリックスを表す型を作成し、その型への参照を渡すことです。

于 2012-10-14T01:22:51.263 に答える