理解双指针的解引用

Understanding dereferencing of double pointers

这是我最近在线测试中问到的预测输出程序。我无法获得准确的输出,因为我不熟悉双指针解引用。我知道后缀操作的优先顺序和副作用,这对理解指针问题起着至关重要的作用。

请通过提供双指针取消引用示例来帮助我处理此代码片段。 有关单指针取消引用的更多信息,这是一个非常有用的答案: Pointer expressions: *ptr++, *++ptr and ++*ptr

    #include <stdio.h>
    int main()

    {
        char *a[] = {"NITK", "SURATH", "KALMAN", "GALO", "BREAK", "REJOIN"};
        char **b[] = {a + 2, a + 3, a, a + 1, a + 5, a + 4};
        char ***c = b;
        *c++;
        printf("%s\t", *++*c);
        printf("%s\t", **c + 2);
        printf("%c", (*(**(c + 2) + 2) + 2));
        return 0;
    }

预期输出:

BREAK EAK T

P.s这道题可能没有实际用处,但对理解双指针的概念会有帮助。

  1. *c++; 应该是 c++; 因为 * 在这里没有任何作用。在此操作之后,它引用了对双指针数组 b (a + 3)

    的第二个值的引用
  2. 取消引用后,它指向指向 a+3 的指针,它会增加(因此它引用指向 a + 4 的指针。另一个取消引用指向 a + 4

  3. 由于之前的操作使 c 指向指向指向 a + 4 的指针,**c 引用 a + 4 所以 **c + 2 引用 a + 4.

    的第三个字符
  4. c + 2是指向a + 1的指针。然后**引用了a + 1。将 2 添加到它引用 a + 1 的第三个字符,即 R。取消引用此指针会得到 char 'R'。将 2 添加到它,你会得到 'T' 假设 ASCII 字符编码。

对于初学者来说,这是一个非常愚蠢的测试。忽略使用混淆代码进行此类测试的公司。不要和白痴打交道。通常此类测试由 low-qualified 程序员给出。

考虑到表达式中使用的数组指示符会隐式转换为指向其第一个元素的指针。

所以这个声明

char ***c = b;

等同于

char ***c = &b[0];

在这个表达式语句中

*c++;

未使用指针的取消引用值。所以这个语句应该写成

c++;

在这条语句之后指针c指向数组的第二个元素b

你可以像这样重写上面的语句

c = &b[1];

现在让我们考虑一下 printf 调用中的表达式

printf("%s\t", *++*c)

取消引用指针 c 你得到左值 b[1],其值为 a + 3。将一元运算符 ++ 应用于此表达式,您将得到 a + 4。最后取消引用这个表达式你会得到左值 a[4] 即输出。

BREAK

现在考虑第二次调用 printf 时的表达式。

printf("%s\t", **c + 2);

取消引用指针 c 第一次您将获得左值 b[1]。在第一次调用 printf 后,它包含值 a + 4。取消引用此表达式,您将获得指向字符串文字“BREAK”的左值 a[4]。添加 2 指针表达式将指向字符串文字的第三个字符。所以会有输出

EAK

最后让我们考虑一下第三次调用printf时的表达式。

printf("%c", (*(**(c + 2) + 2) + 2));

因为 c 指向 b[1] 然后使用指针算法 c + 2 表达式将指向 b[3] 取消引用指针你将得到包含值的左值 b[3] a + 1。取消引用此表达式,您将获得指向字符串文字 "SURATH" 的左值 a[1]。再次应用指针算法,您将获得一个指针,该指针指向字符串文字的第三个元素,即子字符串 "RATH"。取消引用指针表达式,您将得到字符 'R'。将值 2 添加到字符上,您将得到输出的字符 'T'

T

就是这样。