Hi everyone!
I am learning about the subtleties of C-arrays (yes, I know one should use vectors instead, but one still needs to understand classical arrays when reading other peoples'code).
Here are some examples, my question comes at the end.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// wrong example
void print_arr(int arr[]) { // C-array declaration
// or: void print_arr(int* arr) {
int noBytes = sizeof arr; // Wrong! Reason: Same as sizeof(int*)!
int iter = noBytes/sizeof(int);
for(int i = 0; i < iter; ++i) {
cout << arr[i] << ’\n’;
}
}
int main() {
int arr[10]; // C-array definition
// some code
print_arr(arr); // wrong ...
}
|
I will come back to this first example at the end.
To make it right, one can pass the number of elements:
1 2 3 4 5 6
|
// correct example
void print_arr2(int arr[], unsigned int n) {
for(unsigned int i = 0; i < n; ++i) {
cout << arr[i] << ’\n’;
}
}
|
What to do with 2-dimensional arrays?
The number of elements in the "inner" array, is part of the type of the outer array, so it needs to be spelled out in the function parameters:
1 2 3 4 5 6 7 8 9 10
|
void print_arr2D(int arr[][3], size_t n)
// or : void print_arr2D(int (*arr)[3], size_t n) {
for(int i = 0; i < n; ++i) {
for(int j = 0; j < 3; ++j) { // annoying magic number
cout << arr[i][j] << ’ ’;
}
cout << ’\n’;
}
cout << ’\n’;
}
|
Now, we use a template to make this work for arbitrary columns:
1 2 3 4 5 6 7 8 9 10 11
|
template<typename arrtype>
void print_arr2DT(arrtype arr, size_t n) {
const unsigned int cols = sizeof arr[0] /sizeof arr[0][0];
for(unsigned int i = 0; i < n ; ++i) {
for(unsigned int j = 0; j < cols; ++j) {
cout << arr[i][j] << ’ ’;
}
cout << ’\n’;
}
cout << ’\n’;
}
|
I understand it until here. But now, the book claims that we can pass the array by reference so that
even the row number n does not need to be passed anymore:
1 2 3 4 5 6 7 8 9 10 11 12
|
template<typename arrtype>
void print_arr2DT(arrtype &arr) { // pass by reference
constexpr unsigned int rows = sizeof(arrtype)/ sizeof(arr[0]); // can use sizeof(arrtype) now
constexpr unsigned int cols = sizeof arr[0] /sizeof arr[0][0];
for(unsigned int i = 0; i < rows; ++i) {
for(unsigned int j = 0; j < cols; ++j) {
std::cout << arr[i][j] << ’ ’;
}
std::cout << ’\n’;
}
std::cout << ’\n’;
}
|
My question: Why could I not have passed by reference in the first example as well? There, the author claimed we can't use sizeof() and need to pass the number of rows manually.
I understood the rasoning that the array name is just a pointer. Passing by reference would still mean that sizeof() would just give the size of the pointer. But why is it different here?