Reputation: 1480
I just wanted to know--is this the correct way to pass a pointer to a 2-D Array by reference in a function?
bool test::testTheNumber(test (*arr)[9][9], int testNumber, int row, int column)
{
if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
....
}
My "theRow" and "theColumn" answers are very similar to the test function:
bool sodoku::theRow(sodoku (*arr)[9][9], int testNumber, int row)
bool sodoku::theColumn(sodoku (*arr)[9][9], int testNumber, int column)
In my main.cpp, I have a pointer to a 2d array and I called my functions like this:
test *arr[9][9];
theRow(arr,0,0);
theColumn(arr,0,0);
testTheNumber(arr,0,0,0,0);
Would the array pass by reference or would I have to use a & instead of a *? I am just a little confused as I'm not entirely sure how 2-D arrays would work.
Thanks.
Upvotes: 0
Views: 875
Reputation: 208323
bool test::testTheNumber(test (*arr)[9][9], int testNumber, int row, int column)
is this the correct way to pass a pointer to a 2-D Array by reference in a function?
Technically this is not passing the array by reference, but rather passing a pointer to the array by value. The semantics are quite similar otherwise. To pass an array of 9x9 integers to the function by reference the signature would be:
bool test::testTheNumber(test (&arr)[9][9], int testNumber, int row, int column)
Note that the only difference is changing the *
(pointer) to &
(reference). The use of this would be:
int main() {
test array[9][9];
test t;
t.testTheNumber(array,1,2,3);
}
(Whether this does make sense or not is a completely different thing... you might want to provide a non-member function rather than a member function, for example)
Both of Geoff suggestions suggestion are equivalent and the problem they have is that in changing the interface the size of the array is not fixed in the signature. That is, the function will take an array of 9x9, but it will also accept arrays of 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);
}
As you can see, by changing the type of the function argument, the first dimension is now free and the compiler will gladly accept any size there, so it is a worse option than the original one.
Finally, my suggestion would be creating a type that represents a 9x9 matrix and passing a reference to that type.
Upvotes: 0
Reputation: 721
C arrays are quite confusing and C++ inherited the confusion to be compatible with C. To understand how arrays work, the basics are:
1) array variables behave in expressions as a pointer to its first element except that it is constant (i.e. you cannot do "array = p;") and sizeof(array) will give you the size of the array (size of one element times the number of element) while sizeof(pointer) will give you the size of a pointer.
int array[5];
int* p = array;
Then the following expression are true:
array[0] == *array
sizeof(array) == sizeof(int)*5
sizeof(p) == sizeof(void*)
2) When you define an argument of a function as an array, it is always passed as a pointer to the first element. And behaves in the function as such. In fact, C ignore in that case the size of the passed array. Even more, defining in a function an argument as an array or pointer to an element of the array is considered the same by the compiler. So:
void func(int array[5]);
void func(int array[]);
void func(int *array);
declares the exact same function, and inside this function, sizeof(array)==sizeof(void*)
Because of that, arrays seems to be always passed by reference, looking like a pointer to its first element.
Now, multi dimensional arrays are just in fact single dimensional array whose elements are arrays. The confusing part in C/C++ about that is the confusing way C/C++ defines types in general. So:
test* array[9][9];
Remember that to read C/C++ type, you start from the identifier and that [] and () have precedence, so array is an array of 9 elements (first [9]) which are arrays of 9 elements (second [9]) which are pointers to type "test".
Now for the arr argument in this method:
bool sodoku::theRow(test (*arr)[9][9], int testNumber, int row)
arr is a pointer (parentheses change the precedence) to an array of 9 arrays of 9 "test" elements.
This is very different from the previous "array" variable above, especially because "array" contains pointers to "test" while arr contains "test" element...
BTW, the following declaration is completely identical:
bool sodoku::theRow(test arr[][9][9], int testNumber, int row)
as "arr" can also be interpreted as a pointer to the first element of an array of 9 arrays to 9 "test"...
In practice, what you probably want to do is passing arrays of 9 arrays of "test", so:
boot sudoku::theRow(test arr[][9], int testNumber, int row)
{ ... }
test array[9][9];
sudoku::theRow(array, 0, 0);
And the method could also be defined as:
boot sudoku::theRow(test (*arr)[9], int testNumber, int row)
{ ... }
A lot of information exists on the internet about this very confusing array/pointer mix-up of C/C++, for example: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
Upvotes: 2
Reputation: 2597
This
bool test::testTheNumber(test (*arr)[9], int testNumber, int row, int column)
{
if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
....
}
Or
bool test::testTheNumber(test arr[][9], int testNumber, int row, int column)
{
if(theRow(arr, testNumber, row) && theColumn(arr, testNumber, column))
....
}
The first dimension in the array isn't needed.
Really, arrays are passed by reference by default. You don't need a &
.
For more information, you may want to read this answer to this question.
Upvotes: 2