Kanwal Prakash Singh
Kanwal Prakash Singh

Reputation: 349

what is wrong when i'm trying to access this array (2d ) in c++

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

Answers (4)

rodrigo
rodrigo

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

Franko Leon Tokalić
Franko Leon Tokalić

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

NathanOliver
NathanOliver

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

john elemans
john elemans

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

Related Questions