Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot cast array to pointer

I have the following source:

#include <iostream>
using namespace std;

void main(int j)
{
    char arr[10][10];
    char** ptr;
    ptr = arr;
}

when I compile it using VS2010 I get this error:

error : a value of type "char (*)[10]" cannot be assigned to an entity of type "char **"

I thought arrays in c++ were just pointers. So a char[][] could also be char**. What am I doing wrong?

like image 340
atoMerz Avatar asked Dec 12 '11 17:12

atoMerz


5 Answers

Arrays aren't pointers.

An array decays to a pointer in most circumstances, but this isn't recursive. So a T[] decays to a T *, but a T[][] doesn't decay to a T**.

I suggest reading the whole of the C FAQ chapter on arrays and pointers; in particular, the section on 2D arrays and pointers-to-pointers.

like image 190
Oliver Charlesworth Avatar answered Nov 16 '22 06:11

Oliver Charlesworth


The existing answers, though correct, don't make it very clear that there is a fundamental reason (apart from the language rules) why you cannot cast char [10][10] to char **. Even if you force the cast by saying something like

char arr[2][2];
char ** ptr = (char **)arr;

it won't actually work.

The reason is that in C and C++ a two-dimensional array is laid out in memory as an array of arrays. That is, in C a two-dimensional array is laid out in memory as a single allocation,

arr -> arr[0][0]
       arr[0][1]
       arr[1][0]
       arr[1][1]

You'll notice that arr doesn't point to a char * but to arr[0][0] which is a char; therefore, while arr can be cast to a char *, it cannot be cast to a char **.

The correct forced cast would be

char arr[2][2];
char * ptr = (char *)arr;

If you don't want to force the cast (always a good idea if possible!) you would say

char arr[2][2];
char * ptr = arr[0];

or, to make the outcome clearer,

char arr[2][2];
char * ptr = &arr[0][0];

And you now have (in effect) a pointer to an array of 4 characters. [Proviso: I can't find anything in the C standard that prohibits an implementation from adding padding between two rows of an array, but I don't believe that any real-world implementations do so, and common coding practice depends on the assumption that there will be no such padding.]

If you really needed to convert arr to a char ** you would have to explicitly create an array of pointers:

char arr[2][2]
char * arr_ptrs[2];
char ** ptr;
arr_ptrs[0] = arr[0];
arr_ptrs[1] = arr[1];
ptr = arr_ptrs;

The C language could in principle do this for you automatically if you tried to cast a two-dimensional array to a pointer-to-pointer but that would violate the programmer's expectation that a cast does not have side-effects such as allocating memory.

In Java, by way of comparison, a two-dimensional array is always an array of pointers to arrays, so that the array

char arr[][] = { {'a', 'b'}, {'c', 'd'} };

is laid out in memory as three separate allocations, in arbitrary order and not necessarily adjacent,

arr -> arr[0]
       arr[1]

arr[0] -> arr[0][0]
          arr[0][1]

arr[1] -> arr[1][0]
          arr[1][1]

You will immediately notice that this requires more memory than the equivalent C array, and is slower to evaluate at runtime. On the other hand, it does allow the rows of an array to have different lengths.

like image 25
Harry Johnston Avatar answered Nov 16 '22 05:11

Harry Johnston


The types char[10][10] and char** and char (*)[10] are all different types. However, the first one cannot convert into the second one, it can convert into the third one.

So try this:

char arr[10][10];
char (*ptr)[10];
ptr = arr; //ok

It will work, because as I said object of type char[10][10] can convert into an object of type char (*)[10]. They're compatible types.

like image 25
Nawaz Avatar answered Nov 16 '22 06:11

Nawaz


I thought arrays in c++ were just pointers.

No, an array is a set of objects laid out contiguously in memory. In some circumstances, they are convertible to a pointer to the first element.

So a char[][] could also be char**

No. It is convertible to a pointer to the first one-dimensional array (which is the type char (*)[10] mentioned in the error message); but that array is not a pointer, so it is not convertible to a pointer-to-pointer.

like image 1
Mike Seymour Avatar answered Nov 16 '22 04:11

Mike Seymour


The error exactly tells you whats wrong a double dimensional array can be assigned to an pointer to array not an double pointer. So what you need is:

char (*ptr)[10] = arr; 

What am I doing wrong?

First things first
Arrays are not pointers!! but they act sometimes like pointers.

The rule is:

An expression with array type (which could be an array name) converts to a pointer anytime an array type is not legal, but a pointer type is.

So if you have a single dimensional array:

char arr[10];

Then arr decays to address of the zeroth element it has the type char *. Hence:

char *ptr = arr;

But if you have an 2 dimensional array which is essentially an array of arrays.

 char arr[10][10];

Then arr decays to the pointer to an array of 10 characters.

So, In order to assign arr to something, you will need that something to match the type, which is pointer to an array of characters.
Hence:

char (*ptr)[10] = arr; 
like image 1
Alok Save Avatar answered Nov 16 '22 04:11

Alok Save