收录日期:2020/10/25 07:52:57 时间:2010-09-07 01:26:29 标签:c++,c,arrays

Can someone explain why I can do:

int x[4] = { 0, 1, 2, 3 };
int *p = x;

But cannot do:

int x[2][2] = { 0, 1, 2, 3 };
int **p = x;

Is there a way to be able to assign to **p the x[][]?

TIA

A pointer to int int * can point at an integer within an array of integers, so that's why the first is OK;

int x[4] = { 0, 1, 2, 3 };
int *p = x;

This makes p point to x[0], the first int in x.

A pointer to a pointer-to-int int ** can point at a pointer-to-int within an array of pointers-to-int. However, your second array is not an array of pointers-to-int; it is an array of arrays. There are no pointers-to-int, so there is nothing sensible to point int **p at. You can solve this in two ways. The first is to change the type of p so that it is a pointer-to-array-of-2-ints:

int x[2][2] = { 0, 1, 2, 3 };
int (*p)[2] = x;

Now p points at x[0], the first int [2] in x.

The alternative is to create some pointers-to-int to point at:

int x[2][2] = { 0, 1, 2, 3 };
int *y[2] = { x[0], x[1] };
int **p = y;

Now p points at y[0], which is the first int * in y. y[0] in turn points at x[0][0], and y[1] points at x[1][0].

Using the pointer notation you can do this

*(p + n) will return back a value in the subscript n which is equivalent of p[n], a "single dimension array"

*( * (p + i) + j) will return back a value in the subscripts i and j which is equivalent of p[i][j], a "double dimension array"

This will prove that using array subscripts [] decays into pointers as per the rule - see ANSI C Standard, 6.2.2.1 - "An array name in an expression is treated by the compiler as a pointer to the first element of the array", furthermore, ANSI C Standard 6.3.2.1 - "A subscript is always equivalent to an offset from a pointer", and also ANSI C Standard 6.7.1 - "An array name in the declaration of a function parameter is treated as a pointer to the first element in the array"

If you are not sure in understanding how pointers and arrays work, please see my other answer which will explain how it works...

Please ignore anyone who says arrays and pointers are the same - they are not...

No, there's no way to assign the array to an "int **", because a two-dimensional array is an array of arrays, not an array of pointers.

You could for instance do:

  int x1[2] = {0, 1};
  int x2[2] = {2, 3};
  int *x[2] = {x1, x2};
  int **p = x;

... and maybe that would be an acceptable equivalent to what you are trying to do (depending on what exactly that is of course!).

Update: If you must keep x as a two-dimensional array, you could also do: int (*p)[2] = x; which gives you a pointer-to-array-of-int.

There is no way to meaningfully initialize you variable p with x. Why? Well, there's no way to answer your question until you explain how you even came to this idea. The type of p is int **. The type of x is int[2][2]. These are two different types. Where did you get the idea that you should be able to assign one to the other?

If you really need to access elements of your x through a pointer of type int **, you have to do it indirectly. You have to create an additional intermediate array that will hold pointers to first elements of consecutive rows of array x:

int *rows[2] = { x[0], x[1] };

and now you can point your p to the beginning of this intermediate array

int **p = rows;

Now when you assess p[i][j] you get x[i][j].

There's no way to do it directly, without an intermediate array.

If you are really using c++ instead of c, you can get this effect by using std::vector (or some other collection type).

typedef std::vector<std::vector<int> > intmatrix;
intmatrix x;
intmatrix::iterator p = x.begin();

or some such.

It's all about Standard Conversion rule ($4.2)

An lvalue or rvalue of type “array ofN T” or “array of unknown bound of T” can be converted to an rvalue of type “pointer to T.” The result is a pointer to the first element of the array.

The type of od and td respectively are

char [3]

char [1][3]

This means that od has type 'array of 3 chars' (N = 3, T = char).

So in accordance with the above quote, it can be converted to 'pointer to char'

Therefore char *p = od; is perfectly well-formed

Similarly the type of od is 'array of 1 array of 3 chars' (N = 1, T = array of 3 chars).

So in accordance with the above quote, it can be converted to 'pointer to array of 3 chars'

Therefore char (*p)[3] = td; is perfectly well-formed

Is there a way to be able to assign to **p the x[][]?

No. Because type of td[x][y] for valid x and y is char. So what you can really do is char *pc = &td[0][0].