"Wonder" <sa******@gmail .com> writes:
Irrwahn Grausewitz <ir*******@free net.de> writes:
[attribution added]
p p is ...
(*p) ... a pointer ...
(*p)[3] ... to an array of three ...
int (*p)[3] ... ints.
Thanks a lot! Your method is very useful.
In other words: if you post code here, make sure it's C.
I rewrite the program in pure C, here it is:
#include <stdio.h>
int main()
{
int (*p)[3];
/* printf("%x\t%x\ t%x\n",*p[0],*p[1],*p[2]); */
printf("%x\t%x\ t%x\n",p[0],p[1],p[2]);
printf("%x\t%x\ t%x\n",&p[0],&p[1],&p[2]);
}
And I recompiled it by gcc under cygwin. The output is:
4 10 1c
4 10 1c
The first printf would cause core dump, but now I can understand it if
here p is a pointer to an int array which has 3 elements.
My question is why the second and third printf give the same result,
seems p[i] is same as &p[i] here.
Let's try a modified version of your program.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int (*p)[3];
p = malloc(sizeof *p);
if (p == NULL) {
exit(EXIT_FAILU RE);
}
printf("p[0] = %p\n", (void*)p[0]);
printf("&p[0] = %p\n", (void*)&p[0]);
free(p);
return 0;
}
On one implementation, I get:
p[0] = 0x460210
&p[0] = 0x460210
As we've established, p is a pointer to an array of 3 ints.
You didn't initialize p, so its value is garbage. Any attempt to look
at whatever it points to invokes undefined behavior (I got a segmentation
fault). I've corrected this with the malloc() call.
The correct format for printing a pointer value is "%p", not "%x".
The "%p" format expects an argument of type void*; the casts are
necessary (even though you may be able to get away without them).
The prefix to an indexing operator [] is actually a pointer. If it's
the name of an array, as in
int arr[10];
arr[5];
the array name is implicitly converted to a pointer to its first
element. Since p is already a pointer, no such conversion is
necessary.
Remember that, by definition, x[y] is equivalent to *(x+y). In this
case, p[0] is equivalent to *(p+0), which is equivalent to *p. So the
expression p[0] gives you the thing that p points to, which happens to
be an array of 3 ints.
So p[0] is an array of 3 ints. In most contexts, an expression of
array type is implicitly converted to a pointer to its first element.
So in the printf() statement, p[0] is converted to a pointer-to-int,
and its value happens to be 0x460210. (Actually, it's pseudo-random
garbage, but we'll leave that aside for now.)
Note that we considered this conversion rule in two different
contexts. For p, the prefix to the indexing operator, the rule
doesn't apply, because p is already a pointer (to an array of 3 ints).
For p[0], an array of 3 ints, the rule does apply, and it's converted
to a pointer-to-int.
In the second printf, we apply the "&" (address-of) operator to p[0].
This is one of the contexts in which the conversion to pointer
*doesn't* take place. (Another is the operand of the sizeof
operator.) So &p[0] is the address of an array-of-3-ints. p[0] and
&p[0] have different types, but they yield the same raw pointer value
when converted to void* and printed with "%p".
And in your original program, p[1] actually refers to *another* array
of 3 ints, the second element of the array of arrays-of-3-ints to
which p points. In my version of your program, I only allocated
enough memory for a single array-of-3-ints; if I wanted to play with
p[1], I'd have to allocate more memory.
This all seems confusing because, frankly, it is. I went down a
couple of blind alleys while writing this, and I'm not at all certain
that there are no errors in what I've written.
There really aren't many cases where it makes sense to have a pointer
to an array of 3 ints. Usually it makes much more sense to have a
pointer to int, which can be used to access an array of ints. If you
really need an array of items, where each item contains 3 ints, you
might be better off wrapping the array-of-3-ints in a struct and
declaring a pointer to the struct type. Even if you can keep the
complications of a pointer-to-fixed-size-array-of-whatever straight in
your head, the next person to read your code may not be able to.
For a better general understanding of the relationship between arrays
and pointers, read section 6 of the C FAQ,
<http://www.eskimo.com/~scs/C-faq/faq.html>. (In fact, read the whole
thing if you haven't already.)
And before assuming that everything I've written here is correct, wait
a while until the other regulars have had a chance to pick it apart.
--
Keith Thompson (The_Other_Keit h)
ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.