0
void main()
{
   int a[]={3,5,6,10,2};
   int *p;
   p=&a;
   int **q;
   q=&p;
   p=p+2;
   (*p)++;
   printf("%u\n",p);
   printf(" %u \n",&a);
   printf("%u",q);
}

This is giving the output as:

738565800
738565792 
738565784

How is the value of q being printed as always 8 lesser than that of the address of a? Could someone explain that relation?

Varaquilex
  • 3,447
  • 7
  • 40
  • 60

4 Answers4

1

Use %p specifier to print address

printf("%p\n", (void*)p);
printf(" %p \n",(void *)&a);
printf("%p", (void *)q);  

Using %u specifier to print pointer values invokes undefined behavior. %u expects unsigned int.
You can use sizeof function to calculate the size of these types

printf("%zu\n",sizeof(p));    // 4
printf("%zu \n",sizeof(&a));  // 4 
printf("%zu",sizeof(q));      // 4
haccks
  • 104,019
  • 25
  • 176
  • 264
  • So what about the value which I get when I print using %u? I understood how p got the value. But what about the value of q? –  Oct 07 '13 at 18:19
  • THese are the values which I got on giving %p : p=0x7fff759edd98 a=0x7fff759edd90 q=0x7fff759edd88 –  Oct 07 '13 at 18:20
  • have you casted the arguments? – haccks Oct 07 '13 at 18:24
  • @haccks It seems that `printf("%d\n",sizeof(p))` suffers from the same type of undefined behavior; you must use `%zu` (not sure about this part) or cast `sizeof` to `int` – anatolyg Oct 07 '13 at 19:09
  • @anatolyg; Return type of `sizeof` is `size_t` (`unsigned int`). – haccks Oct 07 '13 at 19:26
  • 1
    @haccks Maybe pressing the [issue](http://stackoverflow.com/q/2524611/509868) too much, but it seems on topic here – anatolyg Oct 08 '13 at 06:56
1

Let's remove unnecessary cruft from your program, and fix it to print pointers correctly (as suggested by haccks):

int a[]={3,5,6,10,2};
int *p;
printf("%p\n", (void*)&p);
printf("%p\n", (void*)&a);

I guess it behaves in the same way on your system (I cannot tell for sure; this kind of stuff is implementation-dependent).

The compiler (or OS) allocates addresses to local variables in order (descending or ascending - this can differ). It seems that your system gives bigger addresses to variables declared earlier in the source code.

The difference in addresses is the size of each variable (in bytes).

You can visualize the storage of variables like this:

+------+
| p    | (address 0x7fff759edd88)
| p    | (... continued at address 0x7fff759edd8c)
+------+
| a[0] | (address 0x7fff759edd90)
| a[1] | (address 0x7fff759edd94)
| a[2] | (address 0x7fff759edd98)
| a[3] | (address 0x7fff759edd9c)
| a[4] | (address 0x7fff759edda0)
+------+

Note that your original program prints the address of p in a rather roundabout way (first assigns it to q, then prints q).

Community
  • 1
  • 1
anatolyg
  • 26,506
  • 9
  • 60
  • 134
0

This isn't your issue (anatolyg has answered the question you were asking), but you have a type mismatch. The type of the expression &a is int (*)[5] (pointer to 5-element array of int). Types matter for pointers as well as everything else. Assuming you want p to be a simple pointer to int, you'd simply write

int *p;
p = a;

Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array; so, no need to use the & operator in this case.

Also, use int main( void ) instead of void main().

Both of these issues should have been flagged by your compiler; make sure you compile with all warnings enabled.

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

There's no meaningful explanation of the behavior of your code at the level of C language. You code sample contains erroneous code as well as code producing undefined behavior. So, the results you observe can only be explained by half-random half-implementation-dependent manifestations of that undefined behavior.

In particular, the following issues exist in your code.

p = &a;

This is illegal. &a has type int (*)[5], while p is declared as int *. Assignment from such incompatible type is not allowed in C. It is a constraint violation in C, i.e. it is what is normally supposed to result in compilation error.

void main()

Function main in C is required to return int, not void.

printf("%u\n",p);
printf(" %u \n",&a);
printf("%u",q);

Trying to print pointer values by using %u format specifier causes undefined behavior. %u requires an unsigned int argument, not a pointer argument.

Now, the typical behavior of such broken code (if you manage to force it through some lenient compiler) would usually produce the follwing. The value of q you observe is the location of pointer p in memory. The value of &a you observe is the location of array a in memory. So, the difference of 8 bytes that you observe simply means that p and a are located 8 bytes from each other in memory. p resides at lower address, while a resides at higher address. That's all there is to it.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765