Reputation: 349
below is the code that I'm trying to run
#include <iostream>
using namespace std;
int foo(int **a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int **)a);
}
when I have four elements in this array, shouldn't the value *(a+3) return a value 4, instead of that its returning an address and when i try to dereference that address (i.e. **(a+3)) i get segfault 11
Upvotes: 1
Views: 75
Reputation: 98516
Actually you are defining an array of arrays of integers. It can decay to a pointer to an array of integers, but it will not decay into a pointe to a pointer of integers.
It will help if you draw the memory layout:
+---------+---------+---------+---------+
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
If you let it decay into a pointer-to-array-of-integer:
int (*pa)[2] = a;
+---------+---------+---------+---------+
| pa[0] | pa[1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
Note how sizeof(*pa) = 2 * sizeof(int)
. Each of these values can decay into a pointer to integer, but never into a pointer to a pointer:
int *p = pa[0];
Anyway, you can cast the decayed pointer-to-array-of-integer into a pointer to integers and access the four values directly:
int *p = (int*)a;
std::cout << p[3] << std::endl;
std::cout << *(p + 3) << std::endl;
The memory will be like this:
+---------+---------+---------+---------+
| p[0] | p[1] | p[2] | p[3] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
But if you cast it into a int**
you will get meaningless values, because in memory there are no pointers, just integers.
Upvotes: 6
Reputation: 1508
When you dereference int**
you get int*
. However, you are dereferencing a location with a value 4
that is interpreted as int*
. That's why cout prints 0x4
, because it formats it as an address. Try taking int*
as parameter:
#include <iostream>
using namespace std;
int foo(int *a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int *)a);
}
It prints 4 then.
This is just an example of how to fix up this piece of code in particular, and is not the right way of doing things. Also as @rodrigo stated in the comments of his answer, if the size of an int is not equal to the size of its pointer, this is not going to work. I just wanted to show you why you thought it was printing an address - because it is being interpreted as one.
Upvotes: 0
Reputation: 181027
A array is not a pointer. Yes it can decay to a pointer that does not mean it is one. If you want to pass a 2d array then you can use
int foo(int a[][2]);
or if you want to take any size array then you can use
template<std::size_t N>
int foo(int a[][N]);
Upvotes: 2
Reputation: 2676
You are dereferencing too far. a already points to the first element in the array. So **a treats the first value in the array as an address instead of a value. Try
foo((int *)a)
Upvotes: 0