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?
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.
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.
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.
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 bechar**
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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With