Reputation: 49270
I recently came across this question in an Interview process. I need some help to understand the logic behind 2nd output of this program.
#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); //1st statement
printf("%s ", *--*++cpp+3); //2nd statement
printf("%s ", *cpp[-2]+3); //3rd statement
printf("%s ", cpp[-1][-1]+1); //4th statement
return 0;
}
output:- TEST sQuiz Z CQ
What I understand from above code:
for the sake of simplicity we can consider cp[]
as {QUIZ TEST MCQ GeksQuiz}
1st statement:
**++cpp
-> cpp
will points to base address of TEST
and dereferencing it 2 times gives TEST
which is fine.
but in 2nd statement I can't demystify the logic:
*--*++cpp+3
-> ++cpp
points to MCQ
*++cpp
will be the address of M
, --*++cpp
will be previous address to M
, now I'm stuck here. how it's getting sQuiz
as output?
(afaik ++(suffix) and * have same precedence and right to left associativity)
(DISCLAIMER: please broaden your mind. not all codes are meant for product development. this code evaluates the understanding of C pointers)
Upvotes: 3
Views: 579
Reputation: 106022
After first printf
, cpp
is pointing to c+2
.
CP
+------+
| |
0 | C+3 +----------------------------------------------------------------+
| | |
| | |
+------+ |
| | |
1 | C+2 +-------------------------------------------------+ |
CPP --------> | | | |
| | | |
+------+ | |
| +---------------------------------------+ | |
2 | C+1 | | | |
| | | | |
| | | | |
+------+ | | |
| +-----------------------+ | | |
3 | C | v v v v
| |
| | +-------------+------------+-----------+------------+
+------+ C | "GeksQuiz" | "MCQ" | "TEST" | "QUIZ" |
| | | | |
+-------------+------------+-----------+------------+
0 1 2 3
In second printf
, ++cpp
will increment cpp
to c+1
.
*++cpp
will dereference cpp
and will give c+1
.
--
will decrement c+1
by 1
therefore, *--*++cpp
will ultimately give c
.
c+3
will point to the 4th character of "GeksQuiz"
, i.e. s
.
Note that after second printf
cpp
will point to cp[0]
which is pointing to c
now.
+------+
| |
0 | C+3 +----------------------------------------------------------------+
| | |
| | |
+------+ |
| | |
1 | C+2 +-------------------------------------------------+ |
| | | |
| | | |
+------+ | |
| +-------------------------+ | |
2 | C | | | |
CPP -------->| | | | |
| | | | |
+------+ | | |
| +-----------------------+ | | |
3 | C | v v v v
| |
| | +-------------+------------+-----------+------------+
+------+ | "GeksQuiz" | "MCQ" | "TEST" | "QUIZ" |
| | | | |
+-------------+------------+-----------+------------+
0 1 2 3
Upvotes: 5
Reputation: 6793
Initially:
0x100: "GeksQuiz"
0x200: "MCQ"
0x300: "TEST"
0x400: "QUIZ"
0x500: { 0x100, 0x200, 0x300, 0x400 } // c
0x600: { 0x518, 0x510, 0x508, 0x500 } // cp
0x700: 0x600 // cpp
After statement 1:
0x700: 0x608 // ++cpp = 0x608
// *cpp = 0x510
// **cpp = 0x300 = "TEST"
After statement 2:
0x700: 0x610 // ++cpp = 0x610
0x600: { 0x518, 0x510, 0x500, 0x500 } // --*++cpp = 0x500
// *--*++cpp = 0x100 = "GeksQuiz"
// *--*++cpp+3 = 0x103 = "sQuiz"
After statement 3:
// cpp = 0x610
// cpp[-2] = 0x518
// *cpp[-2] = 0x400 = "QUIZ"
// *cpp[-2]+3 0x403 = "Z"
After statement 4:
// cpp = 0x610
// cpp[-1] = 0x510
// cpp[-1][-1] = 0x200 = "MCQ"
// cpp[-1][-1]+1 = 0x201 = "CQ"
Upvotes: 2
Reputation: 5856
*--*++cpp+3
is processed as *(--(*(++cpp)))+3
which means the following:
*++cpp
points to "MCQ"
(due to initial move of the pointer to "next in list" twice), was pointing to "TEST"
after the first printf
was over
--*++cpp
points to "GeksQuiz"
*--*++cpp
points to the beginning of the "GeksQuiz"
, to its first character
Then you advance the resulting pointer by 3, resulting in the output you see.
Upvotes: 4