9

Possible Duplicate:
casting char[][] to char** causes segfault?

I have a 2D array declared like this:

int arr[2][2]={ {1,2},{3,4}};

Now if I do:

int ** ptr=(int**) arr;

and:

cout<<**ptr;

I am getting a segmentation fault (using g++-4.0).

Why so? Shouldn't it be printing the value 1 (equal to arr[0][0])?

Community
  • 1
  • 1
PKG
  • 579
  • 6
  • 17
  • 3
    I think there is a great rule in C++: "If you have to cast, you can't afford it" http://blogs.msdn.com/b/oldnewthing/archive/2009/10/23/9911891.aspx – SergGr Jun 01 '10 at 16:51

6 Answers6

5

You can't cast a linear array to a pointer-to-pointer type, since int** doesn't hold the same data int[][] does. The first holds pointers-to-pointers-to-ints. The second holds a sequence of ints, in linear memory.

jweyrich
  • 31,198
  • 5
  • 66
  • 97
  • Well, you "can", as the OP demonstrates. You just have to do a reinterpret_cast, which the OP unknowingly did because they're using c-style casts. As with all such casts of course the result of accessing the new pointer is UB. The moral the OP should be getting is: use C++ casts in C++. – Edward Strange Jun 01 '10 at 17:06
2

What you do now means creating of arrays of pointers where every pointer was explicitly casted. Therefore, you would have an array of pointers like (0x00001, 0x00002, 0x00003 and 0x00004).

When dereferenced, this pointers cause your segfault.

M. Williams
  • 4,945
  • 2
  • 26
  • 27
2

You are attempting to assign a double pointer variable to an array... this has been covered exhaustively, see here for information on this. Furthermore, since you declared

int arr[2][2] = ...;

and then try to assign arr to a double pointer

int ** ptr = ... ;

which is guaranteed to not work, hence a segmentation fault. Furthermore, that statement int ** ptr=(int**) arr; is actually cast ing one type (i.e. [][]) to another type (i.e. **) despite they are of type 'int'. They are both different and the compiler will interpret that very differently...

You could do it this way:

int *ptr = &arr;

Now *(ptr + 1) will refer to the 0'th row, *(ptr + 2) will refer to the 1'st row and so on. The only onus on you is to not overstep the markers of where arr is used otherwise an overflow can happen or even a segmentation fault...

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
1

No, int ** is a pointer to a pointer to an int, but a 2-D array is an array of arrays, and &(arr[0][0]) is a pointer to an int.

I believe you should be doing this:

int *ptr = arr;
cout<<*ptr; 

or this:

int *ptr = &arr[0][0];
cout<<*ptr; 
Cade Roux
  • 88,164
  • 40
  • 182
  • 265
0

Try

int *ptr = arr;

More Explanation:

You should assign an adress to the pointer, so it can be derefenced(i mean * operator). What you do is, pointing ptr to memory cell that has the adress a[0][0]. Therefore, you get a segmentation fault.

Ayberk
  • 410
  • 10
  • 21
0

int arr[2][2] is not an array of arrays - it is a single 2d array. In memory, it is indistinguishable from int arr[4]

What you really want is

int (*ptr)[2] = arr;
BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
  • Formally, it *is* an array of arrays. But yes, since arrays are laid out contiguously with no padding allowed, an `int [2][2]` is indeed laid out exactly like an `int [4]` in memory. – caf Jun 02 '10 at 05:04