*++*++ppp, *++pp[1], *++(*(1+ppp) Is there any specific difference?(C/C++ pointer problem)

-4
#include <cstdio>
using namespace std;

int main()
{
    const char *p[] = { "aa", "bb", "cc" };
    const char **pp[] = { p + 2, p + 1, p };
    const char ***ppp = pp;

    printf("%s\n", **++ppp );  // bb
    printf("%s\n", *++*++ppp);  // bb
    printf("%s\n", *++pp[1]);   // cc
    // printf("%s\n", *++(*(1+ppp)));   wrong

    return 0;
}

Microsoft VS2015 Output:
bb
bb
cc
Execution exception: 0xC0000005

*++*++ppp, *++pp[1], *++(*(1+ppp) Is there any specific difference? Isn't *++ppp not pp[1]? Isn't *++ppp not *(1+ppp)? Thank you!

c++
c
pointers
asked on Stack Overflow Nov 16, 2019 by Fred Hu • edited Nov 16, 2019 by Fred Hu

1 Answer

0

TL;DR: Yes there is a big difference between *++p and p[1]. The former increments the pointer before dereferencing it, the latter dereferences the elements after the pointed to element. The returned value is the same, but in the first case the pointer is changed.


Important note: Never ever write lines like these in production code! You can do this in experimental and fool's code. But professional code has to be clear and up-front understandable.

I know of several style guides that forbid using increment operators inside other expressions. They have to be on their own lines.


Let's dissect all your lines and look what they do to your variables.

printf("%s\n", **++ppp ); // *(*(++p))

ppp is incremented and points to pp[1]. That's contents points to p+1 which points to "bb" which is printed. Check.

printf("%s\n", *++*++ppp); // *(++(*(++ppp)))

Again ppp is incremented and points to pp[2]. The derefence and pre-increment let it point to p+1. That's contents points to "bb" which is printed. Check.

printf("%s\n", *++pp[1]); // *(++(pp[1]))

This time you increment pp[1] which points to p+2 thereafter. pp itself can't be incremented because it's an array so pp[1] is incremented. OK, p+2 points to "cc" which is printed. Check.

printf("%s\n", *++(*(1+ppp))); // *(++(*(1+ppp)))

The sum 1+ppp points to pp[3] which is after the array pp. Remember, you incremented ppp twice before! Dereferencing this pointer is undefined behaviour and can deliver any value. That value is then interpreted as a pointer to const char ** which you try to increment and dereference once more. Somewhere here this results in an invalid pointer so a segmentation error is thrown. Boom.


And this is what you could have done to investigate your problem to understand how pointers and arrays of pointer work:

#include <cstdio>
using namespace std;

void print_pointers(const char *p[], const char **pp[], const char ***ppp)
{
    printf("p   = %p : %p %p %p\n", p, p[0], p[1], p[2]);
    printf("pp  = %p : %p %p %p\n", pp, pp[0], pp[1], pp[2]);
    printf("ppp = %p\n", ppp);
}

int main()
{
    const char *p[] = { "aa", "bb", "cc" };
    const char **pp[] = { p + 2, p + 1, p };
    const char ***ppp = pp;

    print_pointers(p, pp, ppp);
    printf("%s\n", **++ppp );  // bb
    print_pointers(p, pp, ppp);
    printf("%s\n", *++*++ppp);  // bb
    print_pointers(p, pp, ppp);
    printf("%s\n", *++pp[1]);   // cc
    print_pointers(p, pp, ppp);

    const char ***p1 = 1+ppp;
    printf("      1+ppp   = %p\n", p1);
    const char **p2 = *p1;
    printf("    *(1+ppp)  = %p\n", p2);
    ++p2;
    printf(" ++(*(1+ppp)) = %p\n", p2);
    const char *p3 = *p2;
    printf("*++(*(1+ppp)) = %p\n", p3);
    printf("%s\n", p3); // printf("%s\n", *++(*(1+ppp)));

    return 0;
}
answered on Stack Overflow Nov 16, 2019 by the busybee • edited Nov 16, 2019 by the busybee

User contributions licensed under CC BY-SA 3.0