这些类型如何(int(*ptr)[3])= a; (其中a = = int a [] [3] = {1,2,3,4,5,6})语句在C中工作?增量"ptr"给出了意想不到的结果

Shi*_*ora 3 c arrays pointers pointer-arithmetic

对于以下代码:

#include <stdio.h>
int main()
{
    int a[][3] = {1, 2, 3, 4, 5, 6};
    int (*ptr)[3] = a;
    printf("%d %d ", (*ptr)[1], (*ptr)[2]);
    ++ptr;
    printf("%d %d\n", (*ptr)[1], (*ptr)[2]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

应该打印什么?我期待:

2 3 3 4

但输出是:

2 3 5 6

我期待输出,2 3 3 4 因为最初ptr它指向二维数组的第一行a[][3].因此(*ptr)[1],首先printf会给我们2,就像明智的(*ptr)[2]会给我们3.但是++ptr在线之后它将开始指向第一行的第二个元素a[][3].因此(*ptr)[1],第二行现在应该给我们3,同样(*ptr)[2]应该给我们4.

眠りネ*_*ネロク 6

ptr是类型int (*)[3]:

int (*ptr)[3]
Run Code Online (Sandbox Code Playgroud)

该类型的ptr指定如何指针airthmetic要执行上是怎么回事ptr.


对于以下更一般的情况:

int *p;
// ...
int (*ptr)[N] = p;
ptr += M; // same address as p[M * N]
Run Code Online (Sandbox Code Playgroud)

增加指针会M导致地址递增,M * N * sizeof(int)而不是M * sizeof(int)像您预期的那样.

这是指针算法的工作原理,因为元素的类型ptr指向的是int [N]和不是int.


语句++ptr;执行后,ptr指向第三个元素a.增量是以三个类型的元素int而不是单个元素的步骤完成的,也就是说,在你的情况下N = 3.


小智 5

让我们逐行处理。


int a[][3] = {1, 2, 3, 4, 5, 6};
Run Code Online (Sandbox Code Playgroud)

a具有类型“ 3的数组int”。这行相当于

int a[][3] = {{1, 2, 3}, {4, 5, 6}}; /* alternate */
Run Code Online (Sandbox Code Playgroud)

通过这条备用线(它a是一个数组数组)可以更清楚地看到。这将有助于理解下几行。

int (*ptr)[3] = a;
Run Code Online (Sandbox Code Playgroud)

ptr的类型为“指向3的数组的指针int”。由于数组到指针的衰减,ptr将指向aint (*ptr)[3] = &a[0])中的第一个数组。

printf("%d %d ", (*ptr)[1], (*ptr)[2]);
Run Code Online (Sandbox Code Playgroud)

解引用ptr给出a[0],因此将打印

2 3

++ptr;
Run Code Online (Sandbox Code Playgroud)

这似乎是您感到困惑的地方。递增指向元素的指针会使指针指向如果它们在数组中的下一个元素将位于的位置。在这种情况下,当前元素指出,之后的下一个元件在一个数组(该元件为第3个数组intS,不是一个单一的int)。因此,增加指针使其指向3 ints 的下一个数组(恰好是a[1])。

printf("%d %d\n", (*ptr)[1], (*ptr)[2]);
Run Code Online (Sandbox Code Playgroud)

现在我们知道ptr指向a[1],我们可以看到(*ptr)[1]等于a[1][1],即5;且(*ptr)[2]等同于a[1][2],它是6。所以,现在的总输出为:

2 3 5 6