13

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?

3
  • The C FAQ covers this: c-faq.com/aryptr/pass2dary.html Commented Dec 12, 2011 at 17:13
  • 6
    "I thought arrays in c++ were just pointers" - if you could do me a favour: find the person who told you that, call them a muppet, and point them at this question. If you read it in a book, take it back for a refund. If it was a library book, put a bit of paper into that page with some relevant URLs and a note that the author is a muppet. Commented Dec 12, 2011 at 17:26
  • possible duplicate of conversion of 2D array to pointer-to-pointer Commented Apr 17, 2015 at 16:18

8 Answers 8

12

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. I'm accepting Nawaz's answer since he provided solution.
@AtoMerZ: I didn't provide a solution because you didn't specify what you wanted to do!
Oh yes, sorry. I wanted to get rid of the error. Still a vote up.
11

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.

Comments

6

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.

3 Comments

One question: Isn't char(*ptr)[10] a pointer to a 1d char array? If so, isn't a 1d char array same as 'char*'? If this is also true, then I have a pointer to a pointer to a char -> char**.
@AtoMerZ: No. 1D array is not char*. 1D array can convert into char*. But chained conversion is not allowed in C++. There is only one conversion from char[10][10] to char (*)[10]. And no further conversion. If A can convert into B, and B can convert into C. then you cannot write C=A which is chained conversion, which is not allowed.
"Isn't char(*ptr)[10] a pointer to a 1d char array?" -- It's more specific than that. It's specifically a pointer to a 1d array of 10 characters, no more, no less.
1

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.

Comments

1

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; 

Comments

0

Arrays are NOT just pointers -- arrays are arrays. Arrays are not first-class types, however, so you can't use them in many places. The thing that causes your confusion is that array names CAN be implicitly converted into pointers to the array's first element, which means that you can use an array in many places where you need a pointer and it 'just works'. This, however, is not one of those places.

Comments

0

Arrays are not pointers (I notice a lot of books tend to make you think this, though). They are something completely different. A pointer is a memory address while an array is a contiguous set of some data.

In some cases, an array can decay to a pointer to its first element. You can then use pointer arithmetic to iterate through the contiguous memory. An example of this case would be when passing an array to a function as a parameter.

What you probably want to do here is something like:

char arr[10];
char * i = &arr[0];

Obviously you'll need to use 2D arrays and char** in your case. I'll leave that to you to figure out :)

Comments

0

When you cast ar[10][10] to pointer you will get a array of pointer as said above *ar[10] and not **ar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.