3

The compiler states "assignment from incompatible pointer type" when the row of the 2D array is not mentioned, I always thought an array without brackets means the address of the first element, in this case address of the element twodstring[0][0]

Compiler does not state an error when the row is mentioned, I was wondering why is this the case?

#include<stdio.h>

int main()
{

  char onedstring[]={"1D Array"};
  char twodstring[][5]={"2D","Array"};
  char *p1,*p2;

  p1=onedstring;
  p2=twodstring;
  p2=twodstring[1];

}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

2 Answers2

5

A two-dimensional array

char a[M][N];

can be declared using a typedef the following way

typedef char T[N];

T a[M];

So a pointer to the first element of the array a can be declared like

T *p = a;

where T is an alias for the type char[N]. Now making the reverse substitution we can write

char ( *p )[N] = a;

That is elements of a two-dimensional array are one-dimensional arrays.

This declaration

char ( *p )[N] = a;

is equivalent to

char ( *p )[N] = &a[0];

where a[0] has the type char[N]. So the pointer points to the first "row" of the array.

Dereferencing the pointer you will get an object of the type char[N].

Pay attention to that a two-dimensional array can be declared like

char ( a[M] )[N];

So substituting the one-dimensional array declarator a[M] for pointer you will get

char ( a[M] )[N];
char (  *p  )[N] = a;

If you will declare a pointer like this

char *p1;

then you may write for example

p1 = a[1];

in this expression a[1] is a one-dimensional array of the type char[N]. Using the expression as an initializer the array is converted to pointer to its first element that has the type char *.

So this expression statement

p1 = a[1];

is equivalent to

p1 = &a[1][0];

Dereferencing this pointer you will get an object of the type char.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Just out of curiosity, what would be the case if it were to be a 3D array? Would the above answer apply for a 3D array as well? –  Nov 02 '17 at 18:44
  • @AMD So if you have char a[N]; then the pointer is char *p = a; If you have char a[M][N]; then the pointer is char ( *p )[N] = a; If you have char a[N1][N2][N3]; then the pointer is char ( *p )[N2][N3]; That is the left-most dimension is substituted for the pointer. – Vlad from Moscow Nov 02 '17 at 18:49
4

Let's look at these lines:

char twodstring[][5]={"2D","Array"};
char *p2;
p2=twodstring;

In the last line, you just write the identifier of an array. This evaluates to a pointer to the first array element. But this first array element doesn't have the type char -- it is an array itself with the type char [5].

If you want this assignment to work, you have to declare p2 with the correct type like this:

char twodstring[][5]={"2D","Array"};
char (*p2)[5];
p2=twodstring;
  • 1
    I may just be late in my time zone, and I should go rest, but what does `char ()` in `char ()[5]` mean? – StoryTeller - Unslander Monica Nov 02 '17 at 18:04
  • A placeholder where the declared identifier would go ... I've seen this often to specify an array type. –  Nov 02 '17 at 18:08
  • `char ()[5]` is the type of a function with unspecified argument list returning `char[5]`. (Which is a constraint violation, since functions cannot return arrays). You probably meant `char[5]` – M.M Nov 02 '17 at 22:25
  • See C11 6.7.7 (footnote 147) – M.M Nov 02 '17 at 22:32
  • @M.M yes, it's not *formally* correct (e.g. as operand of `sizeof`), but you still see it used that way for clarity in free-form explanations. I definitely don't mean `char[5]` because this is, although syntactically correct, quite misleading, especially for learners (for the same reason I find `int*` misleading). But alright, I'll change it to `char [5]` -- IMHO not as obvious, but still correct when used in C source. –  Nov 02 '17 at 23:24
  • I've never seen `char()[5]` written to mean `char[5]` outside of your answer here . Also I would suggest that if someone finds the correct type misleading then a good remedy to that is to learn more about the type system – M.M Nov 02 '17 at 23:50
  • @Felix Palmen "But this first array element doesn't have the type char -- it is an array itself with the type char [5]." Can you explain this statement in a bit of detail? I always thought char is the type, and [5] would be a size declaration, I never knew there is type char[5]? –  Nov 03 '17 at 03:27
  • @AMD not sure how to answer this ... read **§6.5.2 Types** in [the latest C11 draft](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf). In a nutshell, `char` is the *basic type*, an array of char is a *derived type*. You can't write `char[5] x;` as a declaration if that's what you mean, and that's the reason I preferred to put a placeholder when talking about it, but indeed, if you need to write **just a type name**, this works by omitting the identifier in the declaration syntax ... the type of `char x[5]` therefore is `char [5]`. –  Nov 03 '17 at 08:33