我最近在面试过程中遇到了这个问题。 我需要一些帮助来理解这个程序的第二个输出背后的逻辑。
#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;
}
输出: - TEST sQuiz Z CQ
我从上面的代码中理解:
为了简单起见,我们可以将cp[]
视为{QUIZ TEST MCQ GeksQuiz}
第一个陈述:
**++cpp
- &gt; cpp
会指向TEST
的基地址,并且将其解除引用2次会产生TEST
,这很好。
但在第二个陈述中我无法揭开逻辑的神秘面纱:
*--*++cpp+3
- &gt; ++cpp
MCQ
的{{1}} *++cpp
地址为M
的地址,--*++cpp
将是M
的先前地址,现在我被困在这里。如何将sQuiz
作为输出?
(afaik ++(后缀)和*具有相同的优先级和从右到左的关联性)
(免责声明:请扩大您的想法。并非所有代码都用于产品开发。此代码评估对C指针的理解)
答案 0 :(得分:5)
首先printf
后,cpp
指向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
在第二个printf
中,++cpp
会将cpp
增加到c+1
。
*++cpp
会取消引用cpp
,并会c+1
--
将c+1
递减1
因此,*--*++cpp
最终会c
。{
c+3
将指向"GeksQuiz"
的4 th 字符,即s
。
请注意,在第二个printf
cpp
后,指向cp[0]
的{{1}}现在指向c
。
+------+
| |
0 | C+3 +----------------------------------------------------------------+
| | |
| | |
+------+ |
| | |
1 | C+2 +-------------------------------------------------+ |
| | | |
| | | |
+------+ | |
| +-------------------------+ | |
2 | C | | | |
CPP -------->| | | | |
| | | | |
+------+ | | |
| +-----------------------+ | | |
3 | C | v v v v
| |
| | +-------------+------------+-----------+------------+
+------+ | "GeksQuiz" | "MCQ" | "TEST" | "QUIZ" |
| | | | |
+-------------+------------+-----------+------------+
0 1 2 3
答案 1 :(得分:4)
*--*++cpp+3
被处理为*(--(*(++cpp)))+3
,表示以下内容:
*++cpp
指向"MCQ"
(由于指针初始移动到&#34;列表中的下一个&#34;两次),指向"TEST"
后的第一个printf
1}}结束了
--*++cpp
指向"GeksQuiz"
*--*++cpp
指向"GeksQuiz"
的开头,指向其第一个字符
然后将结果指针前进3,得到您看到的输出。
答案 2 :(得分:2)
最初:
0x100: "GeksQuiz"
0x200: "MCQ"
0x300: "TEST"
0x400: "QUIZ"
0x500: { 0x100, 0x200, 0x300, 0x400 } // c
0x600: { 0x518, 0x510, 0x508, 0x500 } // cp
0x700: 0x600 // cpp
在陈述1之后:
0x700: 0x608 // ++cpp = 0x608
// *cpp = 0x510
// **cpp = 0x300 = "TEST"
在声明2之后:
0x700: 0x610 // ++cpp = 0x610
0x600: { 0x518, 0x510, 0x500, 0x500 } // --*++cpp = 0x500
// *--*++cpp = 0x100 = "GeksQuiz"
// *--*++cpp+3 = 0x103 = "sQuiz"
在陈述3之后:
// cpp = 0x610
// cpp[-2] = 0x518
// *cpp[-2] = 0x400 = "QUIZ"
// *cpp[-2]+3 0x403 = "Z"
在声明4之后:
// cpp = 0x610
// cpp[-1] = 0x510
// cpp[-1][-1] = 0x200 = "MCQ"
// cpp[-1][-1]+1 = 0x201 = "CQ"