繁体   English   中英

具有复指针运算的 C 程序的输出

[英]Output of C program with complex pointer arithmetic

我正在准备涉及猜测 C 代码输出的编程测验。

经过长时间的尝试,我仍在努力理解以下代码的输出:

#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;
}

输出

TEST sQuiz Z CQ

谁能帮我理解为什么这个输出?

创建以下临时变量有助于理解一些表达式。

char s1[] = "GeksQuiz";
char s2[] = "MCQ";
char s3[] = "TEST";
char s4[] = "QUIZ";

char *c[] = {s1, s2, s3, s4};
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;

第一个printf

printf("%s ", **++cpp);

**++cpp具有cpp = cpp+1的副作用,计算结果为

**(cpp+1) ,与

*(cp[1]) ,与

*(c+2) ,等同于:

c[2] ,等同于:

s3 ,其评估为"TEST" 。(最初是 s2 更正)

在该语句的末尾, cppcp+1相同。

第二个printf

printf("%s ", *--*++cpp+3);

*--*++cpp+3

*(--(*(++cpp))) + 3 ,具有cpp = cpp+1副作用,并评估为:

*(--(*(cpp+1))) + 3 ,与

*(--(*(cp+2))) + 3 ,与

*(--(cp[2])) + 3

*(--(cp[2])) + 3具有cp[2] = cp[2]-1 = c+1-1 = c的副作用,计算结果为:

*(cp[2]-1) + 3 ,与

*(c+1-1) + 3 ,与

*(c) + 3 ,这与

c[0] + 3 ,与

s1 + 3 ,计算结果为"sQuiz"

在该语句的末尾, cppcp+2相同。

第三个printf

printf("%s ", *cpp[-2]+3);

*cpp[-2]+3

*(cpp[-2])+3 ,与

*(cp)+3因为前面对cpp . 的++操作,与

c[3]+3 ,与

s4+3 ,其计算结果为"Z" 。(最初更正为 s3+3)

第四个printf

printf("%s ", cpp[-1][-1]+1);

cpp[-1][-1]+1

*(cpp-1)[-1]+1 ,与

*(*(cpp-1) -1) + 1 ,与

*(*(cp+1) -1) + 1 ,与

*(cp[1] -1) + 1 ,与

*(c+2-1) + 1 ,与

*(c+1) + 1 ,与

c[1] + 1 ,与

s2 + 1 ,其计算结果为"CQ"

它有助于绘制指针的图片,但在 StackOverflow 上很难做到:

cpp: cp
cp: c+3, c+2, c+1,  c
c:   s0,  s1,  s2,  s3
s0: 'G', 'e', 'K', 's', 'Q', 'u', 'i', 'z', '\0'
s1: 'M', 'C', 'Q', '\0'
s2: 'T', 'E', 'S', 'T', '\0'
s3: 'Q', 'U', 'I', 'Z', '\0'

这是一个表格,显示了每个数组,以及静态字符串(为了便于讨论,我已经给出了名称)。

现在让我们看看这些语句的作用:

printf("%s ", **++cpp);

增加cpp (改为指向cp[1] ),然后 deref 两次——第一个得到c+2 ,第二个s2然后打印: TEST

printf("%s ", *--*++cpp+3);

增加cpp (现在指向cp[2] ),取消引用并减少它(将cp[2]更改为现在指向c[0] ),然后再次取消引用(获得s0 )。 最后添加 3 ( s0+3 ) 并打印: sQuiz

printf("%s ", *cpp[-2]+3);

cp[2] (即cp[0] == c+3 )取回 2 个槽的值,然后取消引用它以获得s3 然后加3,并打印: Z

printf("%s ", cpp[-1][-1]+1);

cp[2]取回 1 个槽的值(即cp[1] == c+2 ),然后从中取回一个槽的值(即c[1] == s1 ),然后加 1 和打印: CQ


要记住的重要事项是:

  • 每个*[]是一个解引用,它引用指针指向的值
  • 递增/递减运算符对最后一个解除引用的事物进行操作(如果尚未解除引用,则直接对变量进行操作。
  • 一元运算符的优先级高于二元运算符,因此(除括号外)所有一元后缀运算符都首先出现,然后是一元前缀,然后才是二元运算符。
  • []实际上是一元后缀运算符,而不是中缀二元运算符(即使它有两个操作数),因为第二个操作数在括号内。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM