0

Can somebody explain why in the output 3 4 4 is getting printed instead of 4 4 4?

#include <stdio.h>

int main(){

    int a[] ={0,1,2,3,4};
    int *p[] = {a,a+1,a+2,a+3,a+4};
    int **ptr= p; 

    ptr++;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    *ptr++;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    *++ptr;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    ++*ptr;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);

    return 0;
}

Output

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

1 Answers1

5

For starters pay attention to that a difference of two pointers has the type ptrdiff_t. You may not use the conversion specifier %d with objects of this type. You have to use %td. As for example

printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);

How does the expression *++ptr is different from ++*ptr?

This expression

*++ptr

is equivalent to

*( ++ptr )

that is at first the pointer is incremented and points to the next element of an array and then it is dereferenced providing an lvalue of the pointed element.

This expression

++*ptr

that is equivalent to

++( *ptr )

that is at first the pointer is dereferenced providing an lvalue to the pointed element and then the element itself is incremented.

As for the shown code

   int a[] ={0,1,2,3,4};
   int *p[] = {a,a+1,a+2,a+3,a+4};
   int **ptr= p; 

   ptr++;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   *ptr++;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   *++ptr;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   ++*ptr;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);

then initially the pointer ptr points to the first element of the array p.

   int **ptr= p; 

then the pointer is incremented

   ptr++;

and now it points to the second element of the array p.

As a result this expression

ptr-p

yields the number of elements between the two pointers ptr and p (in this expression the array designator is converted to a pointer to its first element) that is equal to 1.

As ptr points to the element with the value a + 1 of the array p then the expression

*ptr-a

also yields the value 1. And the expression

**ptr

yields the value of the expression a[1].

This expression-statement

*ptr++;

in fact is equivalent to

ptr++;

because the dereferencing of the pointer does not have a side effect.

Now the pointer points to the third element of the array p. And this statement

 printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);

outputs

2 2 2

Again this statement

   *++ptr;

is equivalent to the statement

   ++ptr;

because the dereferencing does not have a side effect. Now the pointer points to the forth element of the array p.

And this statement

   printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);

outputs

3 3 3

In this statement

   ++*ptr;

there is incremented the element of the array p (the forth element) pointed to by the pointer ptr. That is the forth element of the array is now equal to a+4

So the array p now looks like

int *p[] = { a, a + 1, a + 2, a + 4, a + 4 };

So this statement

   printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);

outputs

3 4 4
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I appreciate your enthusiasm in writing a custom answer, but there *had* to be a duplicate for this one. ;-) Sorry. – DevSolar Jan 19 '22 at 13:40