Reputation: 3568
I'm experimenting with the concept of pointer to multi-dimension array in C. Suppose I want to process a multi-dimensional array via a function. The code kinda looks like this:
#include <stdio.h>
void proc_arr(int ***array)
{
// some code
}
int main(int argc, char **argv)
{
int array[10][10];
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
array[i][j] = i * j;
}
}
proc_arr(&array);
return 0;
}
The problem is, when I want to access array
inside proc_arr
, i can't. From my understanding, we should access it this way:
void proc_arr(int ***array)
{
(*array)[0][1] = 10;
}
So I derefer the array
to tell the compiler that I want to go to that address and get the value. But somehow, it crashes. I've tried several combinations of *
and parentheses and still can't make it work. I'm pretty sure it's because of me not understanding pointers and pointers of pointers.
Oh, and I've noticed that it's different if we work with a char **
(array of string) too, like for argv and envp. But for envp, I somehow can access it with (*envp)
. Why?
Here's the function that procces envp (and worked):
int envplen(char ***envp)
{
int count = 0;
while((*envp)[count] != NULL)
{
count++;
}
return count;
}
Also, can I somehow access envp
in the envplen
function with only envp
, but still pass it by reference?
Thanks before.
Upvotes: 4
Views: 448
Reputation: 32510
The problem is because int array[10][10]
allocated on the stack does not lay out memory the way you think it does. This is because arrays are not pointers. The memory is still laid out in a linear array, not a "two dimensional" array, even though that's what the subscripts might indicate. In other words, the memory for int array[10][10]
looks like the following:
starting address: ending address:
| Block_1 of 10 int | Block_2 of 10 int | ... | Block_10 of 10 int |
So when you implicitly convert the array to an int***
, and then try to access the array like (*array)[1][10], what this actually translates to is something like *(*((*array) + 1) + 10)
, and the memory layout for such an operation wants to see memory setup like the following:
int*** array
|
|
| Pointer |
|
|
| Pointer_0 | Pointer_1 | ... | Pointer 10 |
| | |
| | | Block of 10 int |
| |
| | Block of 10 int |
|
|Block of 10 int|
Upvotes: 8
Reputation: 123458
You have a type mismatch. Given the declaration int array[10][10]
, the type of the expression &array
will be int (*)[10][10]
, not int ***
. If you change your function prototype to read
void proc_arr(int (*array)[10][10])
then your code should work as written.
The following table shows the types for various array expressions given a particular declaration.
Declaration: T a[M]; Expression Type Decays To ---------- ---- --------- a T [M] T * &a T (*)[M] *a T a[i] T Declaration: T a[M][N]; Expression Type Decays To ---------- ---- --------- a T [M][N] T (*)[N] &a T(*)[M][N] *a T [N] T * a[i] T [N] T * &a[i] T (*)[N] *a[i] T a[i][j] T Declaration: T a[M][N][O]; Expression Type Decays To ---------- ---- --------- a T [M][N][O] T (*)[N][O] &a T (*)[M][N][O] *a T [N][O] T (*)[O] a[i] T [N][O] T (*)[O] &a[i] T (*)[N][O] *a[i] T [N] T * a[i][j] T [N] T * &a[i][j] T (*)[N] *a[i][j] T a[i][j][k] T
The pattern for higher-dimensioned arrays should be clear.
Upvotes: 4
Reputation: 6126
This won't work:
void proc_arr(int ***array)
{
(*array)[0][1] = 10;
}
Because, behind the scenes the compiler will have to change this into an offset into memory relative to the start of the array. That means it needs to know the dimensions of the array. You have not declared those in the function signature.
Upvotes: 2