5

I am new to pointers and learning basics of pointers. I want to know the difference between *ptr and *(&ptr + 1) from the below code.

#include<stdio.h>
int main()
{
     int a[3] = {1, 2, 3};
     int *ptr = a;

     printf("*ptr = %d\n",*ptr);
     printf("&ptr = %p\n",&ptr);

     printf("(&ptr + 1) = %p\n",(&ptr + 1));
     printf("*(&ptr + 1) = %d\n",*(&ptr + 1));

     return 0;
}       

From my analysis gcc produced the following output,

*ptr = 1    // as ptr = a, Ultimately *ptr will print the first value of array i.e. 1
&ptr = 0x7fffa7e97788   // Starting Address of array or address of first element
(&ptr + 1) = 0x7fffa7e97790   //address of next element in the array
*(&ptr + 1) = 1  // I want to know how this is getting dereffered 

Thanks in Advance.

arahan567
  • 227
  • 2
  • 10

4 Answers4

9

&ptr is the address of the pointer variable ptr. This address in unrelated to the address of the array.

*(&ptr + 1) is undefined behavior because &ptr + 1 is one step past the address of ptr. Dereferencing such a pointer produces undefined behavior.

What you probably meant was *(ptr + 1).

usr
  • 168,620
  • 35
  • 240
  • 369
  • I am using 64-bit ubuntu and the difference between the addresses is exactly 8 byte that is 64-bit, and it is probably giving the next address as you can see but not the past address if i use (&ptr + 1). can you explain me why? – arahan567 Dec 25 '14 at 16:43
  • I don't understand this question. What do you mean by "past address"? Why would you expect to see a smaller (=past?) address if you add 1 to a pointer? Do you understand that `&ptr + 1` points to nothing? – usr Dec 25 '14 at 17:22
  • Thank You very much I got it, Just I got a little confusion with address arithmetic with you explanation i resolved it. – arahan567 Dec 25 '14 at 17:31
7

It seems that the compiler placed defined objects on the stack the following way

--------------------------------
|   ptr   | a[0] | a[1] | a[2] | 
--------------------------------

Thus &ptr is the address where ptr is allocated. &ptr + 1 is the next address after ptr and at the same time it is the address of a[0].

Take into account that it is unspecified in which order the compiler has to place local variables on stack.

Also it seems that in the environment where the program was compiled sizeof( int * ) that corresponds to sizeof( *( &ptr + 1 ) ) is equal to sizeof( int ) and in turn equal to 4. Or sizeof( int * ) is equal to 8 but sizeof( int ) is equal to 4. As you are using format specifier %d in printf for expression *( &ptr + 1 ) then exactly a[0] is outputed.

By the way you can check whether this scheme corresponds to the actual placement of the variables by printing

printf("(&ptr + 1) = %p\n", &ptr + 1 );
printf("(&a[0]) = %p\n",  &a[0] );

If the addresses will not be equal then it means that there is some arbitrary value at the address &ptr + 1 that does not correspond to a[0].

As for the question in the title of your post

Difference Between *ptr and *(&ptr + 1)

then *ptr corresponds to a[0] while using expression *(&ptr + 1) results in undefined behaviour because you are trying to dereference address after ptr.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • (&ptr + 1 is the next address of the ptr and at the same time it is the address of a[0])? will you please explain me how compiler is doing this? – arahan567 Dec 25 '14 at 16:44
  • @arahan567 The compiler places variables on the stack one after another and if it is required then aligning their addresses. It seems that the compiler placed the array after ptr without any padding bytes after ptr. So the array starts at the address after ptr. – Vlad from Moscow Dec 25 '14 at 16:48
  • Since the OP reports sizeof(int) = 4 and sizeof(int *) == 8, it might make sense to give `ptr` a larger section in the diagram. (eg, make the box containing ptr twice as big as the box containing a[0]) – William Pursell Dec 25 '14 at 17:02
1

ptr is a pointer and it points to some valid memory location in your case.

&ptr is the address of your pointer and it can be assigned to a double pointer

int **ptr1 = &ptr; 

Else the address of your first element is given just by ptr.

If you want to parse through your array then have

for(i=0;i<4;i++)
{
printf("Value %d is stored in %p\n",ptr[i],(void *)(ptr+i));
}

(&ptr+1) being dereferenced leads to undefined behavior as this is not the memory which is allocated by you. &ptr is under your control not the location after it i.e. &ptr+1

Gopi
  • 19,784
  • 4
  • 24
  • 36
0

Well, this seems an interesting one. Firstly, as you would be knowing *ptr gives value of a[0],ptr contains the address of a[0] and &ptr is the address of ptr i.e integer pointer variable.

With this in mind, when you print *ptr, the value of a[0] i.e. 1 will get printed, (&ptr+1) would be address one step after the address of ptr and *(&ptr+1) would print the value at the address (&ptr+1). In above code,address of a[0] is immediately after the address of ptr (i.e &ptr). So when you print *(&ptr+1), it would print 1 because &ptr+1 is pointing to a[0]. This depends on the memory assigned to the variables.

Declare the above variables as global and *(&ptr+1) would print value of zero (if '*(&ptr+1)' is not pointing to any location because global variables are initialized to zero). Also, observe the difference in the address assigned to the variables, when declared as global and local . Hope this will help.

Shivakumar
  • 427
  • 2
  • 15
  • Thank you shiva kumar you are right as global variables become the part of data segment we will get the garbage value. But here the case is with stack segment so probably i think there will be no issue with memory. – arahan567 Dec 25 '14 at 19:07
  • Global variables are initialized to zero and not garbage value. – Shivakumar Dec 26 '14 at 08:19