为什么这个指针算术在 2D 数组上起作用

why does this pointer arithmetic on a 2D array work?

本文关键字:2D 数组 起作用 指针 为什么      更新时间:2023-10-16

我写了以下代码:

#include <iostream>
using namespace std;
int main()
{
    int a[10][10];
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            a[i][j] = i * j;
    cout << *(*(a + 3) + 4) << endl;
    return 0;
}

我期待它打印一些垃圾数据或分段错误。我得到的是12。我在 c 和 c++ 中都测试了它(分别使用 gcc 和 g++(,尽管我还没有测试过,但我在 VS 上也是如此。为什么会这样,是否有此行为的官方文档?

*(a + b)=a[b]

取 a 的地址,移动它 b 并在相应的地址取值

所以*(*(a + 3) + 4)意味着*(a[3]+4)这意味着a[3][4]=12

声明

int a[m][n];

表示m数组的数组,其中每个此类内部数组的大小为 n

我记得最后一个指数变化最快。

在表达式(a + 3)中,对外部数组的a引用衰减为指向该外部数组的项的指针。 即指向数组大小n指针。然后,+ 3将内部数组字节大小的 3 倍添加到a -as-指针的地址。

取消引用此操作会得到指向int的指针。

将 4 加到其中,您将在内部数组中占据 4 个位置。

这个方案的美妙之处在于它也适用于"交错数组",指针数组,因为那里的类型是不同的。

关于它的非常可悲的事情是它不能很好地与C++派生类一起使用,因为Derived数组衰减到指向Derived的指针,然后可以隐式转换为指向Base的指针,当索引时产生形式上的未定义行为(Derived的大小可以大于Base的大小(。

有关详细说明,请参阅此问题。

二维数组([][], not **(在内存中是连续的,因此您可以使用以下公式访问元素:

*((int *)array + X * NUMBER_OF_COLUMNS + Y);

std::cout << *((int *)a + 3 * 10 + 4);

当你想要一个简单的答案时,用typedef s构建复杂类型

这意味着:

int a[10][10];

将是:

typedef int a10[10]; //a10 is array of 10 ints 
a10 a[10]; //a is array of 10 a10s

现在了解尺寸和位置:

sizeof(a) = 10 * 10 * sizeof int
sizeof(a[0]) = is  10 * sizeof int
a+1 is equal to &a[1]

当您将指针递增 3 时,它是按类型大小的平均增量。

address of a[1] == address of a[0] + sizeof(a[0])

因此:

*(*(a + 3) + 4) == a[3][4] 
您可以使用

*(arr + index( 或 arr[index] 为数组编制索引。它们在语义上不同,但在功能上是相同的。

有关详细信息,请参阅此堆栈溢出讨论。

*(指针 + 索引(和指针 [] 之间的区别

你得到的输出是12的,它是绝对正确的。您为数组的每个元素都做了a[i][j] = i*j ;。现在您打印*( *(a + 3) + 4)a[3][4]相同。就像你a[i][j] = i*j一样,你现在有a[3][4] = 3*4 = 12。所以它会打印12.