0

Consider the following code:

#include <stdio.h>

int main()
{
  static int a[]={0,1,2,3,4};
  int *p[]={a,a+1,a+2,a+3};            /* clear up to this extent */
  printf(("%u\n%u\n%u",p,*p,*(*p)));   /* how does this statement work? */
  return 0;
}

Also is it necessary to get the value of addresses through %u,or we can use %d also?

5
  • 1
    You can even use %p which is meant for pointer values and actually it is preferred. Commented Apr 12, 2011 at 17:28
  • Are you initializing p here or is this declared somewhere else?? Commented Apr 12, 2011 at 17:28
  • @Alfred Nobel: Neither. You can't print pointers neither through %unot through %d. Pointers are printed through %p. Your printf statement produces undefined behavior because your are trying to use %u with pointers, which makes your "how does this statement work" question meaningless. It doesn't work. Commented Apr 12, 2011 at 17:31
  • @Andrey: I WANT TO SAY THAT THE OUTPUT GIVEN BY THIS STATEMENT IS NOT CLEAR TO ME.........., Commented Apr 12, 2011 at 17:36
  • @Alfred Nobel: One more time: your code produces undefined behavior. Its output is meaningless. There's no way to understand something that is meaningless. There's no output there. There's just random garbage. Trying to pick it apart is a waste of time. That's what "undefined behavior" means in C language. That's the only thing you need to understand. Commented Apr 12, 2011 at 17:52

5 Answers 5

1

Okay, you've created an array of integers and populated it with the integers from 0 to 4. Then you created a 4 element array of pointers to integers, and initialized it so its four elements point to the first four elements of a. So far, so good.

Then the printf is very strange. printf is passed a single argument, namely ("%u\n%u\n%u",p,p,(*p)). This is a comma-expression which means that the comma-separated expressions will be calculated in turn, and only the last one returned. Since the very first thing is a literal, and not an expression, I'd expect it to generate an error. However, without the extraneous parentheses, you have:

printf("%u\n%u\n%u\n",p, *p, *(*p));

This is legal. Three values are passed to printf, interpreted as unsigned integers (which actually only works on some systems, since what you are actually passing in are pointers in the first two cases, and they aren't guarateed to be the same size as unsigned ints) and printed.

Those values are p, *p and **p. p is an array, and so the value of p is the address of the array. *p is what p points to, which are the values of the array. *p is the first value, *(p+1) is the second value, etc. Now *p is the value stored in p[0] which is the address of a[0], so another address is printed. The third argument is **p which is the value stored at (*p), or a[0], which is 0

Sign up to request clarification or add additional context in comments.

2 Comments

If *p is 0 (a[0]), then **p is an illegal indirection, which should throw an error.
+1 for you too. @Nicklamort, *p refers to the first value in p[] (a pointer to a[0]), it is not a[0] itself.
1

Do you have an extra pair of parens in your printf statement?

Anyway, you can think of this statement:

printf("%u\n%u\n%u",p,*p,*(*p));

like following a trail of pointers.

  • p is the pointer itself, printing it should print out the pointer's value which is the address of what it points to. In your case its an array of (int *)'s.
  • *p is a dereferencing operation. It allows access to the object that p points to. In the other answers you see notes made about *p being equivalent to p[0]. That's because p is pointing to the beginning of your structure, which is the start of the array.
  • **p is a dereferencing operation on the pointer object that p points to. Extending the example in the previous point, you can say that **p is equivalent to *(p[0]) which is equivalent to *(a) which is equivalent to a[0].

One tip that might help you when trying to decipher these sorts of statements is that keep in mind the precedence rules of C and insert parens between expressions in the statement to break up the statement. For the **p, inserting parens would do this: *(*p) which makes it clear that what you're doing is to follow two pointers to the final destination.

1 Comment

@Jeff - Ha ha. Thank you. I try to make up for lack of speed with coherence.
1

With those extra parentheses, the commas become comma operators so only the final **p is passed to printf. Since printf expects its first argument to be a pointer to a character string, and on most systems pointers and integers have the same size, so the integer 0 is interpreted as a NULL pointer, and printf prints nothing at all. Or it crashes. That's the trouble with undefined behavior.

Comments

0

Your printf() arguments work like so:

  • p is an address (it's an array of pointers)
  • *p is also an address (it's equivalent to p[0], which is just a)
  • *(*p) is an integer (it's a[0])

1 Comment

@Alfred p is an array, as you've declared it. When used in the context you have above, its value is just an address. Specifically, its the address to the first element of the array. I really recommend that you read a book on C programming; that will be far more enlightening than just posting questions on Stack Overflow.
0

My memory on C pointers is a tiny bit rusty, but let me see if I can recall.

p should be a memory location, it points to nothing else, other than p.

*p dereferences (goes to the memory location and returns the value there) p. since p itself is a pointer to pointers (*p[] can be also written as **p) when we dereference p we get the first value in the array definition, or the address of a.

**p dereferences *p. *p is the address of a. If we dereference that, we'll get the value we put in the first location of a, which is 0

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.