Im quite confused that what is difference between these two initializations:
int (*p)[10];
and
int *p[10]
I know they both can point to 2D array whose element count in row is 10....
Im quite confused that what is difference between these two initializations:
int (*p)[10];
and
int *p[10]
I know they both can point to 2D array whose element count in row is 10....
The first is a pointer to array, the second is an array of pointers.
To elaborate a bit on the correct answers here already:
The first line:
int (*p)[10];
declares that "p" is a pointer to the memory address of an array with the capacity of 10 ints. It can be read in English as: "integer-pointer 'p' points to 10 sequential ints in memory".
The second line:
int *p[10]
Declares that "p[]" is an array of 10 pointers to integers. This is an array of memory addresses that point to integers. In this case, "p" is a sequence of 10 pointers in memory (which happen to be the memory addresses of other ints).
int (*p)[10];
+------+ +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| p | =========================>|(*p)[0]|(*p)[1]|(*p)[2]|(*p)[3]|(*p)[4]|(*p)[5]|(*p)[6]|(*p)[7]|(*p)[8]|(*p)[9]|
+------+ +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
sizeof p
will return sizeof (void *)
(4 on 32 bit systems, 8 on 64 bit systems)
sizeof *p
will return 10*sizeof (int)
(40 on most systems)
int *p[10]; is the same as int* (p[10]);
p
+------+------+------+------+------+------+------+------+------+------+
| p[0] | p[1] | p[2] | p[3] | p[4] | p[5] | p[6] | p[7] | p[8] | p[9] |
+------+------+------+------+------+------+------+------+------+------+
sizeof p
will return 10*sizeof (void *)
(40 on 32 bit systems, 80 on 64 bit systems)
sizeof *p
will return sizeof (int *)
(4 on 32 bit systems, 8 on 64 bit systems)
In your first example, p is pointer to array of 10 integers. In the second example, p is an array of 10 pointers.
You can dynamically allocate an object of type "pointer to array of ten int" as follows.
int (**ptr)[10] = new (int (*)[10]);
Note, no space for any ints is allocated; only the pointer itself.
You can allocate an array of 10 ints as follows:
int *ptr = new int[10];
What you can't do (without explicit casting) is assign a pointer to a dynamically allocated array of 10 int to a pointer of type int (*)[10]
. Whenever you allocate an array via new, even if you use a typedef
, the type of the new expression is a pointer to the first element of the array; the size of the array is not retained in the type of the new expression.
This is because new[]
expressions can allocate arrays where the size of the array is chosen at runtime so would not always be possible (or even desirable) to encode the array size into the type of the new expression.
As has been suggested, you can dynamically allocate an array of one array of 10 int. The size of the first array is lost from the type information and what you get is a pointer to the first element of the array (of size 1) of the arrays of four int.
int (*p)[10] = new int[1][10];
Even though it is an array of just 1 (arrays of 10 int), you still need to use delete[]
to deallocate p
.
delete[] p;
Of course one should never actually be a position to need to call delete manually.
In the first definition (not initialization), p
is a pointer; in the second, p
is an array of 10 pointers.
As others have pointed out, int (*p)[10]
declares p
as a pointer to a 10-element array of int
, whereas int *p[10]
declares p
as a 10-element array of pointer to int
.
In C, declarations are built around the types of expressions, not objects. The idea is that the form of the declaration should match the form of the expression as it's used in the code.
Suppose that p
is an array of pointers to int
(the second case). To access a particular integer value, you'd subscript into the array and dereference the result, as in
x = *p[i];
Postfix operators like []
and ()
have higher precedence than unary operators like *
, so the above statement is parsed as *(p[i])
(IOW, the *
is applied to the expression p[i]
).
The type of the expression *p[i]
is int
, so the corresponding declaration of p
is int *p[10];
.
Now let's suppose that p
is a pointer to an array of int (the first case). To access a particular integer value, you'd dereference the pointer and then subscript the result, as in
x = (*p)[i];
Again, because []
has higher precedence than *
, we need to use parentheses to explicitly associate the *
with just p
, not p[i]
. The type of the expression (*p)[i]
is int
, so the declaration of p
is int (*p)[10];
.