【发布时间】:2018-05-25 18:31:13
【问题描述】:
我正在尝试学习 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;
}
该行的结果:
printf("%s ", *cpp[-2]+3);
让我感到困惑,但让我逐步解释一下,我是如何理解的。
-
char *c[]- 是指向 char 的指针数组。 -
char **cp[]- 是指向 char 指针的指针数组(我认为这是*c[]的反向包装)。 -
char ***cpp- 是一个指向 char 的指针的指针(我认为这是**cp[]的包装器,用于执行位置修改)。
**++cpp - 因为cpp 指向cp,那么++cpp 将指向cp+1,即c+2,因此双重取消引用将打印TEST。
*--*++cpp+3 - 因为现在cpp 指向cp+1,那么++cpp 将指向cp+2,即c+1,接下来的操作-- 将指向c,所以最后的取消引用将打印sQuiz。
混乱来了:
cpp[-2] - 因为现在cpp 指向cp+2,我可以确认
printf("%p\n", cpp); // 0x601090
printf("%p\n", cp+2); // 0x601090
这里我打印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
所以当我像 *(cpp[0]) 或 **cpp 这样取消引用时,我预计会得到 MCQ 的值 c+1
printf("%p\n", &*(cpp[0])); // 0x601068
但是当我说*(cpp[-2]) 我得到QUIZ,但我宁愿期望得到一些垃圾值。
所以我的问题是:
*--*++cpp+3的魔法是如何工作的,我的意思是--部分修改的内容,当我像这样取消引用**cpp时,允许我得到MCQ而不是TEST,我假设这个指针*++cpp+3保留了应用--后的状态,但还无法想象它是如何工作的。-
为什么下面的工作方式是这样的(
cpp[-2]部分):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
它似乎有相反的顺序,我可以接受&*(cpp[0]) 指向c+1,但我希望&*cpp[1] 指向c+2,而&*(cpp[-1]) 指向c。我在这个问题中找到了:Are negative array indexes allowed in C?
- 我显然混淆了很多东西,并且可能将某些东西称为实际上不是指针的东西,我想掌握指针的概念,所以如果有人告诉我我哪里错了,我会很高兴。
【问题讨论】:
-
如果有人认为只有了解这种糟糕的编码实践才能学习一门语言,那他们就错了。放弃他们。
-
您可能缺少的是方括号可以被认为是一个运算符,因此
cpp[n]一词实际上与*(cpp + n)相同。因此,n 的负值是可以接受的,但在实践中很少使用。所以,负下标只是从指针 cpp 向后移动。 -
@RSahu 说真的。当老师选择提出这样的“陷阱”问题时,我无法忍受。这是一种糟糕的编码实践,任何人都不应该处理。如果这成为生产代码,则意味着该公司未能实施最低限度的代码审查实践。
-
我意识到这个
*--*++cpp+3不应该这样写,但是测验中那些棘手的问题仍然帮助我提高了对指针的理解,别担心,你不会的看不到我的 C 代码,我只会学习指针并离开) -
@MisterAlejandro - 我们只是想说倾斜
*--*++cpp+3并不重要,因为它从未被使用过。我不知道是做什么的,但我不在乎(检查我的grey beard 看看我在不需要这个的情况下工作了多长时间)。你应该把学习的重点放在你可以实际使用的东西上。