I am trying to learn pointers in C, and taking a quiz for this purpose. Here is the question:
#include <stdio.h>
char *c[] = {"GeksQuiz", "MCQ", "TEST", "QUIZ"};
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main()
{
printf("%s ", **++cpp);
printf("%s ", *--*++cpp+3);
printf("%s ", *cpp[-2]+3);
printf("%s ", cpp[-1][-1]+1);
return 0;
}
The result of the line:
printf("%s ", *cpp[-2]+3);
confuses me, but let me explain step by step, how I understand that.
char *c[]
- is array of pointers to char.char **cp[]
- is array of pointers that points to pointer to char (I consider this as a wrapper for*c[]
in reverse order).char ***cpp
- is a pointer to pointer that points to pointer to char (I consider this a wrapper for**cp[]
to perform on place modifications).
**++cpp
- since cpp
points to cp
, then ++cpp
will point to cp+1
which is c+2
, so double dereference will print TEST
.
*--*++cpp+3
- since now cpp
points to cp+1
, then ++cpp
will point to cp+2
which is c+1
, and the next operation --
will give us pointer to c
, so the last dereference will print sQuiz
.
Here comes confusion:
cpp[-2]
- since now cpp
points to cp+2
, which I can confirm with
printf("%p\n", cpp); // 0x601090
printf("%p\n", cp+2); // 0x601090
here I print addresses of pointers in c
printf("c - %p\n", c); // c - 0x601060
printf("c+1 - %p\n", c+1); // c+1 - 0x601068
printf("c+2 - %p\n", c+2); // c+2 - 0x601070
printf("c+3 - %p\n", c+3); // c+3 - 0x601078
so when I dereference like this *(cpp[0])
or **cpp
I expectedly get the value MCQ
of c+1
printf("%p\n", &*(cpp[0])); // 0x601068
but when I say *(cpp[-2])
I get QUIZ
, but I would rather expect to get some garbage value.
So my questions are:
How the magic with
*--*++cpp+3
works, I mean what is modified by the--
part that allows me to getMCQ
instead ofTEST
when I dereference like this**cpp
, I assume that this pointer*++cpp+3
preserves the state after the--
is applied, but cannot imagine yet how it works.Why the following works the way it works (the
cpp[-2]
part):printf("%p\n", &*cpp[1]); // 0x601060 -> c printf("%p\n", &*(cpp[0])); // 0x601068 -> c+1 printf("%p\n", &*(cpp[-1])); // 0x601070 -> c+2 printf("%p", &*(cpp[-2])); // 0x601078 -> c+3
It seems that it has reverse order, I can accept &*(cpp[0])
pointing to c+1
, but I would expect &*cpp[1]
to point to c+2
, and &*(cpp[-1])
to c
. Which I found in this question: Are negative array indexes allowed in C?
- I obviously confuse many things, and may call something a pointer that in reality is not one, I would like to grasp the concept of pointer, so will be glad if someone show me where I am wrong.