Reputation: 1024
I'm using Visual Studio 2013 for C.
main.c
int main()
{
int arr[2][3] = { { 10, 20, 30 }, { 15, 25, 35 } };
int **pArr = arr;
printf("\n\n----SIZE OF----");
printf("\nSizeOf(arr) = %d", sizeof(arr));
printf("\nSizeOf(pArr) = %d", sizeof(pArr));
printf("\n\n----DEREFERENCING THE ADDRESS----");
printf("\narr = %d *arr = %d **arr = %d", arr, *arr, **arr);
printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
return 0;
}
Check out this image for a thrown exception:
On using the break-point the values in pointer pArr
& array arr
are shown:
But when I removed the **pArr
part from the second last line of the code, the program output this:
----SIZE OF----
SizeOf(arr) = 24
SizeOf(pArr) = 4
----DEREFERENCING THE ADDRESS----
arr = 5569760 *arr = 5569760 **arr = 10
pArr = 5569760 *pArr = 10
Pointer pArr
is of type "pointer to pointer to int", and therefore is the address at arr
. Then why can't I access **pArr
after using int **pArr = arr;
?
Upvotes: 0
Views: 171
Reputation: 287
A multidimensional array is a compiler construct. It is a continuous memory area whose the position is abstracted away by the compiler. A computer's physical memory layout is purely single dimensional (a huge array).
So, this following code:
int **pArr = arr;
It translates in the following assembly:
6:hhh1.c **** int **pArr = arr;
41 .loc 1 6 0
42 0032 488D45E0 leaq -32(%rbp), %rax
43 0036 488945D8 movq %rax, -40(%rbp)
And the following (correct) code:
int (*pArr)[3] = arr;
Translates in the following assembly:
6:hhh2.c **** int (*pArr)[3] = arr;
41 .loc 1 6 0
42 0032 488D45E0 leaq -32(%rbp), %rax
43 0036 488945D8 movq %rax, -40(%rbp)
Surprised that it translates exactly the same!? It's because the second code changes how the memory is fetch by the compiler later on your code.
Let's take a look in the assembly of the last printf or yours, the first being the one of the wrong code, and the second being from the right code:
14:hhh1.c **** printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
71 .loc 1 14 0
72 00a0 488B45D8 movq -40(%rbp), %rax
73 00a4 488B00 movq (%rax), %rax
74 00a7 8B08 movl (%rax), %ecx
75 00a9 488B45D8 movq -40(%rbp), %rax
76 00ad 488B10 movq (%rax), %rdx
77 00b0 488B45D8 movq -40(%rbp), %rax
78 00b4 4889C6 movq %rax, %rsi
79 00b7 BF000000 movl $.LC5, %edi
79 00
80 00bc B8000000 movl $0, %eax
80 00
81 00c1 E8000000 call printf
And now, the generated from using the second style:
14:hhh2.c **** printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
71 .loc 1 14 0
72 00a0 488B45D8 movq -40(%rbp), %rax
73 00a4 8B08 movl (%rax), %ecx
74 00a6 488B55D8 movq -40(%rbp), %rdx
75 00aa 488B45D8 movq -40(%rbp), %rax
76 00ae 4889C6 movq %rax, %rsi
77 00b1 BF000000 movl $.LC5, %edi
77 00
78 00b6 B8000000 movl $0, %eax
78 00
79 00bb E8000000 call printf
Wow! See now? It's different.
Upvotes: 1
Reputation: 5351
Change
int **pArr = arr;
To
int *Arr = arr;
int **pArr = &Arr;
Since pArr
is a pointer to a pointer of type int
, you are trying to point it just to a pointer.
so when trying to dereferencing an unknown memory location causes Segmentation fault
Edit:
Consider int arr[]
;
Here &arr
and arr
are memory location. (arr+2) to get the address of arr[2], but not ((&arr)+2) to do the same. Similarly, pArr
is pointing to arr
. When you write *pArr
it is same as **arr
Refer Please explain the difference for more info
Upvotes: 1
Reputation: 53366
Your array arr
and pArr
contains address 0x60f914
. The memory here contains 6 integers are you have initialized.
When your do *pArr
it will give you contains at address 0x60f914
which is 10
. And when you do **pArr
it will give you contains at address 10
.
So the conclusion is 2-D array is not exactly arranged as _pointer-to-pointer-to-int`.
Update:
This is similar to type-casting. If you have some memory address (e.g. void *
) you can type cast it to anything (int *
or my_struct *
) and access the contains of it. But this does not guarantee that structure and contains of that memory is valid for typecasting you are trying to do.
Upvotes: 1
Reputation: 9839
If you use 1-D array, arr
it is pointer to base value of array arr. That is it is as good as &arr[0]
.
When you use 2-D array arr represents pointer to base value, that is arr[0]
which is (*arr)[3]
.
So you should use,
int (*pArr)[3] = arr;
Instead of
int **ptr = arr;
Upvotes: 1
Reputation: 2953
You get an error because *pArr
yields the first element of your 2D array which is 10.
Then, by writing **pArr
in your last printf
you try to dereference 10 which is in hexadecimal 0xa
thus the error message.
Upvotes: 1