I'm learning about pointers:
int x[10];
int *p = &x
this would make a pointer type int to the first element. So, if I had 2D array, I need to use double pointer: first pointer would point to the second dimension of the array. This means :
int x[3][4] = {{1,2,3,4},{5,6,7,8},{9,9,9,9}};
and when I want to point to it I must declare the size of the second dimension like this, right ?
int *p[4] = x;
or there is another way by typing : int **p; ?
and int *p[4] is array of integer pointers which takes 4 * (sizeof(int*)), right?
this would make a pointer type (int) to first element ..
No.
&x is the address of array x and is of type int (*)[10] and you can't assign it to a int * type. Both are incompatible types.
So, if I had 2D array, I need to use double pointer: first pointer would point to the second dimension of the array.
No.
In expressions, arrays converted to pointer to its first elements except when an operand of sizeof and unary & operator. Therefore, in this case the type of x will be int (*)[4] after conversion. You need a pointer to an array of 4 int instead of an array of 4 pointers
int (*p)[4] = x;
To add, the first example is not correct.
x is an array of 10 ints. p is a pointer to int and not a pointer to an array of 10 ints. When assigned to p, x decays to the type pointer to int.
The assignment should be simply:
int* p = x;
Example program:
#include <stdio.h>
main(int argc, char* argv[])
{
int x[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 987, 9, 9 } };
int(*p)[4] = x; printf("p[2][1] %d", p[2][1]);
printf("\nsizeof(p) is : %d \nsizeof(*p) is : %d\n", sizeof(p), sizeof(*p));
}
Output
p[2][1] 987
sizeof(p) is : 4
sizeof(*p) is : 16
In my system (as in yours) int and pointers are 32 bits. So the size of a pointer is 4 and the size of an int is 4 too.
p is a pointer first of all. Not an array. A pointer. It's size is 4 no less no more. That's the answer to your question
Now, just to add some useful information:
p is a pointer to an array of 4 integers. The size of what p points to is 4*4==16. (Try to change int to short in the example program, you'll have sizeof(*p) is : 8)
I can assign p=x because the type is correct, now p contains the address of x and p[0] is the same as x[0] (the same array of 4 int). p[2][3] is the same as x[2][3] and *(p[2]+3). p[2] points to the element 2 of x and p[2]+3 points to the element 3 of x[2]. (all indexing is 0 based)
// Here is not complicated matrix of size
int p[2][4]={
{1,2,3,4},
{5,6,7,8}
};
// points to the first Elements :: ptr
int (*ptr)[0] = &p;
// Now have the same adresse ( ptr and p )
printf("Hello world! %d \n",ptr[1][3]); // show 4
Related
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 7 years ago.
I'm trying to understand the different ways of declaring an array (of one or two dimensions) in C++ and what exactly they return (pointers, pointers to pointers, etc.)
Here are some examples:
int A[2][2] = {0,1,2,3};
int A[2][2] = {{0,1},{2,3}};
int **A = new int*[2];
int *A = new int[2][2];
In each case, what exactly is A? Is it a pointer, double pointer? What happens when I do A+1? Are these all valid ways of declaring matrices?
Also, why does the first option not need the second set of curly braces to define "columns"?
Looks like you got a plethora of answers while I was writing mine, but I might as well post my answer anyway so I don't feel like it was all for nothing...
(all sizeof results taken from VC2012 - 32 bit build, pointer sizes would, of course, double with a 64 bit build)
size_t f0(int* I);
size_t f1(int I[]);
size_t f2(int I[2]);
int main(int argc, char** argv)
{
// A0, A1, and A2 are local (on the stack) two-by-two integer arrays
// (they are technically not pointers)
// nested braces not needed because the array dimensions are explicit [2][2]
int A0[2][2] = {0,1,2,3};
// nested braces needed because the array dimensions are not explicit,
//so the braces let the compiler deduce that the missing dimension is 2
int A1[][2] = {{0,1},{2,3}};
// this still works, of course. Very explicit.
int A2[2][2] = {{0,1},{2,3}};
// A3 is a pointer to an integer pointer. New constructs an array of two
// integer pointers (on the heap) and returns a pointer to the first one.
int **A3 = new int*[2];
// if you wanted to access A3 with a double subscript, you would have to
// make the 2 int pointers in the array point to something valid as well
A3[0] = new int[2];
A3[1] = new int[2];
A3[0][0] = 7;
// this one doesn't compile because new doesn't return "pointer to int"
// when it is called like this
int *A4_1 = new int[2][2];
// this edit of the above works but can be confusing
int (*A4_2)[2] = new int[2][2];
// it allocates a two-by-two array of integers and returns a pointer to
// where the first integer is, however the type of the pointer that it
// returns is "pointer to integer array"
// now it works like the 2by2 arrays from earlier,
// but A4_2 is a pointer to the **heap**
A4_2[0][0] = 6;
A4_2[0][1] = 7;
A4_2[1][0] = 8;
A4_2[1][1] = 9;
// looking at the sizes can shed some light on subtle differences here
// between pointers and arrays
A0[0][0] = sizeof(A0); // 16 // typeof(A0) is int[2][2] (2by2 int array, 4 ints total, 16 bytes)
A0[0][1] = sizeof(A0[0]); // 8 // typeof(A0[0]) is int[2] (array of 2 ints)
A1[0][0] = sizeof(A1); // 16 // typeof(A1) is int[2][2]
A1[0][1] = sizeof(A1[0]); // 8 // typeof(A1[0]) is int[2]
A2[0][0] = sizeof(A2); // 16 // typeof(A2) is int[2][2]
A2[0][1] = sizeof(A2[0]); // 8 // typeof(A1[0]) is int[2]
A3[0][0] = sizeof(A3); // 4 // typeof(A3) is int**
A3[0][1] = sizeof(A3[0]); // 4 // typeof(A3[0]) is int*
A4_2[0][0] = sizeof(A4_2); // 4 // typeof(A4_2) is int(*)[2] (pointer to array of 2 ints)
A4_2[0][1] = sizeof(A4_2[0]); // 8 // typeof(A4_2[0]) is int[2] (the first array of 2 ints)
A4_2[1][0] = sizeof(A4_2[1]); // 8 // typeof(A4_2[1]) is int[2] (the second array of 2 ints)
A4_2[1][1] = sizeof(*A4_2); // 8 // typeof(*A4_2) is int[2] (different way to reference the first array of 2 ints)
// confusion between pointers and arrays often arises from the common practice of
// allowing arrays to transparently decay (implicitly convert) to pointers
A0[1][0] = f0(A0[0]); // f0 returns 4.
// Not surprising because declaration of f0 demands int*
A0[1][1] = f1(A0[0]); // f1 returns 4.
// Still not too surprising because declaration of f1 doesn't
// explicitly specify array size
A2[1][0] = f2(A2[0]); // f2 returns 4.
// Much more surprising because declaration of f2 explicitly says
// it takes "int I[2]"
int B0[25];
B0[0] = sizeof(B0); // 100 == (sizeof(int)*25)
B0[1] = f2(B0); // also compiles and returns 4.
// Don't do this! just be aware that this kind of thing can
// happen when arrays decay.
return 0;
}
// these are always returning 4 above because, when compiled,
// all of these functions actually take int* as an argument
size_t f0(int* I)
{
return sizeof(I);
}
size_t f1(int I[])
{
return sizeof(I);
}
size_t f2(int I[2])
{
return sizeof(I);
}
// indeed, if I try to overload f0 like this, it will not compile.
// it will complain that, "function 'size_t f0(int *)' already has a body"
size_t f0(int I[2])
{
return sizeof(I);
}
yes, this sample has tons of signed/unsigned int mismatch, but that part isn't relevant to the question. Also, don't forget to delete everything created with new and delete[] everything created with new[]
EDIT:
"What happens when I do A+1?" -- I missed this earlier.
Operations like this would be called "pointer arithmetic" (even though I called out toward the top of my answer that some of these are not pointers, but they can turn into pointers).
If I have a pointer P to an array of someType, then subscript access P[n] is exactly the same as using this syntax *(P + n). The compiler will take into account the size of the type being pointed to in both cases. So, the resulting opcode will actually do something like this for you *(P + n*sizeof(someType)) or equivalently *(P + n*sizeof(*P)) because the physical cpu doesn't know or care about all our made up "types". In the end, all pointer offsets have to be a byte count. For consistency, using array names like pointers works the same here.
Turning back to the samples above: A0, A1, A2, and A4_2 all behave the same with pointer arithmetic.
A0[0] is the same as *(A0+0), which references the first int[2] of A0
similarly:
A0[1] is the same as *(A0+1) which offsets the "pointer" by sizeof(A0[0]) (i.e. 8, see above) and it ends up referencing the second int[2] of A0
A3 acts slightly differently. This is because A3 is the only one that doesn't store all 4 ints of the 2 by 2 array contiguously. In my example, A3 points to an array of 2 int pointers, each of these point to completely separate arrays of two ints. Using A3[1] or *(A3+1) would still end up directing you to the second of the two int arrays, but it would do it by offsetting only 4bytes from the beginning of A3 (using 32 bit pointers for my purposes) which gives you a pointer that tells you where to find the second two-int array. I hope that makes sense.
For the array declaration, the first specified dimension is the outermost one, an array that contains other arrays.
For the pointer declarations, each * adds another level of indirection.
The syntax was designed, for C, to let declarations mimic the use. Both the C creators and the C++ creator (Bjarne Stroustrup) have described the syntax as a failed experiment. The main problem is that it doesn't follow the usual rules of substitution in mathematics.
In C++11 you can use std::array instead of the square brackets declaration.
Also you can define a similar ptr type builder e.g.
template< class T >
using ptr = T*;
and then write
ptr<int> p;
ptr<ptr<int>> q;
int A[2][2] = {0,1,2,3};
int A[2][2] = {{0,1},{2,3}};
These declare A as array of size 2 of array of size 2 of int. The declarations are absolutely identical.
int **A = new int*[2];
This declares a pointer to pointer to int initialized with an array of two pointers. You should allocate memory for these two pointers as well if you want to use it as two-dimensional array.
int *A = new int[2][2];
And this doesn't compile because the type of right part is pointer to array of size 2 of int which cannot be converted to pointer to int.
In all valid cases A + 1 is the same as &A[1], that means it points to the second element of the array, that is, in case of int A[2][2] to the second array of two ints, and in case of int **A to the second pointer in the array.
The other answers have covered the other declarations but I will explain why you don't need the braces in the first two initializations. The reason why these two initializations are identical:
int A[2][2] = {0,1,2,3};
int A[2][2] = {{0,1},{2,3}};
is because it's covered by aggregate initialization. Braces are allowed to be "elided" (omitted) in this instance.
The C++ standard provides an example in § 8.5.1:
[...]
float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
[...]
In the following example, braces in the initializer-list are elided;
however the initializer-list has the same effect as the
completely-braced initializer-list of the above example,
float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};
The initializer for y begins with a left brace, but the one for y[0]
does not, therefore three elements from the list are used. Likewise
the next three are taken successively for y[1] and y[2].
Ok I will try it to explain it to you:
This is a initialization. You create a two dimensional array with the values:
A[0][0] -> 0
A[0][1] -> 1
A[1][0] -> 2
A[1][1] -> 3
This is the exactly the same like above, but here you use braces. Do it always like this its better for reading.
int **A means you have a pointer to a pointer of ints. When you do new int*[2] you will reserve memory for 2 Pointer of integer.
This doesn't will be compiled.
int A[2][2] = {0,1,2,3};
int A[2][2] = {{0,1},{2,3}};
These two are equivalent.
Both mean: "I declare a two dimentional array of integers. The array is of size 2 by 2".
Memory however is not two dimensional, it is not laid out in grids, but (conceptionaly) in one long line. In a multi-dimensional array, each row is just allocated in memory right after the previous one.
Because of this, we can go to the memory address pointed to by A and either store two lines of length 2, or one line of length 4, and the end result in memory will be the same.
int **A = new int*[2];
Declares a pointer to a pointer called A.
A stores the address of a pointer to an array of size 2 containing ints. This array is allocated on the heap.
int *A = new int[2][2];
A is a pointer to an int.
That int is the beginning of a 2x2 int array allocated in the heap.
Aparrently this is invalid:
prog.cpp:5:23: error: cannot convert ‘int (*)[2]’ to ‘int*’ in initialization
int *A = new int[2][2];
But due to what we saw with the first two, this will work (and is 100% equivalent):
int *A new int[4];
int A[2][2] = {0,1,2,3};
A is an array of 4 ints. For the coder's convenience, he has decided to declare it as a 2 dimensional array so compiler will allow coder to access it as a two dimensional array. Coder has initialized all elements linearly as they are laid in memory. As usual, since A is an array, A is itself the address of the array so A + 1 (after application of pointer math) offset A by the size of 2 int pointers. Since the address of an array points to the first element of that array, A will point to first element of the second row of the array, value 2.
Edit: Accessing a two dimensional array using a single array operator will operate along the first dimension treating the second as 0. So A[1] is equivalent to A[1][0]. A + 1 results in equivalent pointer addition.
int A[2][2] = {{0,1},{2,3}};
A is an array of 4 ints. For the coder's convenience, he has decided to declare it as a 2 dimensional array so compiler will allow coder to access it as a two dimensional array. Coder has initialized elements by rows. For the same reasons above, A + 1 points to value 2.
int **A = new int*[2];
A is pointer to int pointer that has been initialized to point to an array of 2 pointers to int pointers. Since A is a pointer, A + 1 takes the value of A, which is the address of the pointer array (and thus, first element of the array) and adds 1 (pointer math), where it will now point to the second element of the array. As the array was not initialized, actually doing something with A + 1 (like reading it or writing to it) will be dangerous (who knows what value is there and what that would actually point to, if it's even a valid address).
int *A = new int[2][2];
Edit: as Jarod42 has pointed out, this is invalid. I think this may be closer to what you meant. If not, we can clarify in the comments.
int *A = new int[4];
A is a pointer to int that has been initialized to point to an anonymous array of 4 ints. Since A is a pointer, A + 1 takes the value of A, which is the address of the pointer array (and thus, first element of the array) and adds 1 (pointer math), where it will now point to the second element of the array.
Some takeaways:
In the first two cases, A is the address of an array while in the last two, A is the value of the pointer which happened to be initialized to the address of an array.
In the first two, A cannot be changed once initialized. In the latter two, A can be changed after initialization and point to some other memory.
That said, you need to be careful with how you might use pointers with an array element. Consider the following:
int *a = new int(5);
int *b = new int(6);
int c[2] = {*a, *b};
int *d = a;
c+1 is not the same as d+1. In fact, accessing d+1 is very dangerous. Why? Because c is an array of int that has been initialized by dereferencing a and b. that means that c, is the address of a chunk of memory, where at that memory location is value which has been set to the value pointed to by tovariable a, and at the next memory location that is a value pinned to by variable b. On the other hand d is just the address of a. So you can see, c != d therefore, there is no reason that c + 1 == d + 1.
I came across this question:
In the declaration below , p is a pointer to an array of 5 int
pointers.
int *(*p)[5];
which of the following statements can be used to allocate memory for
the first dimension in order to make p an array of 3 arrays of 5
pointers to type int ?
A. p = new int [3][5]*;
B. p = new int (*)[3][5];
C. p = new int [3]*[5];
D. p = new int *[3][5];
E. p = new int (* [3] ) [5];
What is the answer ?
I am not sure I understand the question. Normally I would create a pointer to an array of 5 int as such int* p[5]; I am curious as to why they did it as int *(*p)[5];
Also what does the question want ? Is it asking to initialize (allocate memory) to the first 3 int pointers ? I would appreciate it if someone could explain this to me
F:
using IPA5 = int*[5];
IPA5 * p = new IPA5[3];
Each element p[0], p[1], p[2] is just a plain, typed array of int*. There's nothing dynamic going on beyond the initial dynamic allocation, where 3 is allowed to be a dynamic quantity.
Then p[0][i] for i in [0, 5) is an int *, which you can use in whatever way you like (which includes making it point to the first element of yet anohter dynamic array).
What you would write as:
int* p[5];
is a five element array of pointers to int.
What this declares:
int *(*p)[5];
is a pointer to a five element array of pointers to int, i.e. a pointer to the type of thing you just wrote.
In other words; you could do:
int * a[5];
int * (*p)[5] = &a;
You can mentally read this incrementally as follows:
(*p) // p is a pointer
(*p)[5] // p is a pointer to an array of size 5
int * (*p)[5] // p is a pointer to an array of size 5 of type pointer to int
You need the parentheses around *p, because otherwise:
int ** p[5];
would declare a 5 element array of type int **, or pointer to pointer to int, which is a different thing entirely.
The question is basically asking you to dynamically allocate memory equivalent to three of what a is above, so answer "D" is the correct one.
The answer is
D. p = new int *[3][5];
all the others are syntactically wrong
to realize the difference between
int * p [5];
int * (*p) [5];
consider this example
int *(*p)[5];
int pp[5];
pp[0][0] = new int [5]; //LHS is int , RHS is int ,, compilation error
p[0][0] = new int [5]; //this works because p[0][0] is a pointer not an int
try thinking about each dimension as adding you additional *
back to the question
int *(*p)[5] is giving you 3 * (***p)
so you can assign
p = int *[3][5]
because it has 3 * as well
int* p[5] has type array of size 5 of int*. It decays to int**, so p + 1 will point to the second element of that array.
int *(*p)[5] has type pointer to array of size 5 of int*. You can think of it as decayed two-dimensional array int* [][5]. So p + 1 will point to the second element of the first dimension of that array, that is to the next byte after 5 pointers to int.
Which leads us to the conclusion that the right answer is D.
(This is not to mention that other answers just don't compile regardless of type of p)
What is the answer ?
D
Normally I would create a pointer to an array of 5 int as such int* p[5]; I am curious as to why they did it as int *(*p)[5];
It is not "normally" because int* p[5] is not a pointer to an array of 5 int, it is an array of 5 pointers to int.
Also what does the question want ? Is it asking to initialize (allocate memory) to the first 3 int pointers ?
It's not clear. There is no way "to make p an array of 3 arrays of 5 pointers to type int", to begin with.
I have created a 2D array, and tried to print certain values as shown below:
int a[2][2] = { {1, 2},
{3, 4}};
printf("%d %d\n", *(a+1)[0], ((int *)a+1)[0]);
The output is:
3 2
I understand why 3 is the first output (a+1 points to the second row, and we print its 0th element.
My question is regarding the second output, i.e., 2. My guess is that due to typecasting a as int *, the 2D array is treated like a 1D array, and thus a+1 acts as pointer to the 2nd element, and so we get the output as 2.
Are my assumptions correct or is there some other logic behind this?
Also, originally what is the type of a when treated as pointer int (*)[2] or int **?
When you wrote expression
(int *)a
then logically the original array can be considered as a one-dimensional array the following way
int a[4] = { 1, 2, 3, 4 };
So expression a points to the first element equal to 1 of this imaginary array. Expression ( a + 1 ) points to the second element of the imaginary array equal to 2 and expression ( a + 1 )[0] returns reference to this element that is you get 2.
Are my assumptions correct or is there some other logic behind this?
Yes.
*(a+1)[0] is equivalent to a[1][0].
((int *)a+1)[0] is equivalent to a[0][1].
Explanation:
a decays to pointer to first element of 2D array, i.e to the first row. *a dereferences that row which is an array of 2 int. Therefore *a can be treated as an array name of first row which further decay to pointer to its first element, i.e 1. *a + 1 will give the pointer to second element. Dereferencing *a + 1 will give 1. So:
((int *)a+1)[0] == *( ((int *)a+1 )+ 0)
== *( ((int *)a + 0) + 1)
== a[0][1]
Note that a, *a, &a, &a[0] and &a[0][0] all have the same address value although they are of different types. After decay, a is of type int (*)[2]. Casting it to int * just makes the address value to type int * and the arithmetic (int *)a+1 gives the address of second element.
Also, originally what is the type of a when treated as pointer (int (*)[2] or int **?
It becomes of type pointer to array of 2 int, i.e int (*)[2]
A 2D-array is essentially a single-dimensional array with some additional compiler's knowledge.
When you cast a to int*, you remove this knowledge, and it's treated like a normal single-dimensional array (which in your case looks in memory like 1 2 3 4).
The key thing to recognize here is that the a there holds the value of the address where the first row is located at. Since the whole array starts from the same location as that, the whole array also has the same address value; same for the very first element.
In C terms:
&a == &a[0];
&a == &a[0][0];
&a[0] == &a[0][0];
// all of these hold true, evaluate into 1
// cast them if you want, looks ugly, but whatever...
&a == (int (*)[2][2]) &a[0];
&a == (int (*)[2][2]) &a[0][0];
&a[0] == (int (*)[2]) &a[0][0];
For this reason, when you cast the a to int *, it simply becomes 1-to-1 equivalent to &a[0][0] both by the means of type and the value. If you were to apply those operations to &a[0][0]:
(&a[0][0] + 1)[0];
(a[0] + 1)[0];
*(a[0] + 1);
a[0][1];
As for the type of a when treated as a pointer, although I am not certain, should be int (*)[2].
When i execute this code
#include<stdio.h>
int main() {
int (*x)[5];
printf("\nx = %u\nx+1 = %u\n&x = %u\n&x + 1 = %u",x,x+1,&x,&x+1);
}
This is the output in C or C++:
x = 134513520
x+1 = 134513540
&x = 3221191940
&x + 1 = 3221191944
Please explain. Also what is the difference between:
int x[5] and int (*x)[5] ?
int x[5] is an array of 5 integers
int (*x)[5] is a pointer to an array of 5 integers
When you increment a pointer, you increment by the size of the pointed to type. x+1 is therefore 5*sizeof(int) bytes larger than just x - giving the 8048370 and 8048384 hex values with a difference of 0x14, or 20.
&x is a pointer to a pointer - so when you increment it you add sizeof(a pointer) bytes - this gives the bf9b08b4 and bf9b08b8 hex values, with a difference of 4.
int x[5] is an array of 5 ints
int (*x)[5] is a pointer to an array of 5 ints
int* x[5] is an array of 5 pointers to ints
int (*x)[5];
declares a pointer to an array.
From the question title, you probably want
int* x[5];
instead, which declares an array of pointers.
int x[5];
declares a plain old array of ints.
int x[5];
declares an array of five ints.
int (*x)[5];
declares a pointer to an array of 5 ints.
You might find cdecl.org useful.
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].