为什么2D数组上的指针算法有效?

时间:2013-12-11 16:13:27

标签: c++ c multidimensional-array pointer-arithmetic

我写了以下代码:

#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上的工作原理相同。为什么这样做,是否有这种行为的官方文档?

6 个答案:

答案 0 :(得分:8)

*(a + b)=a[b]你取a的地址,用b移动并取相应地址的值

所以*(*(a + 3) + 4)表示*(a[3]+4),表示a[3][4] = 12

答案 1 :(得分:4)

声明

int a[m][n];

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

我记得通过记住最后一个索引变化最快。

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

取消引用它会获得指向int的指针。

将4添加到内部数组中将获得4个位置。

这个方案的优点在于它也适用于“锯齿状数组”,指针数组,因为类型不同。

令人遗憾的是,它不适用于C ++派生类,因为Derived数组衰减到Derived指针,然后可以隐式转换为Base的指针{1}},在编制索引时会产生正式的未定义行为(Derived的大小可能大于Base的大小)。

答案 2 :(得分:2)

有关详细说明,请参阅此question

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

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

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

答案 3 :(得分:1)

您可以使用*(arr + index)或arr [index]索引数组。它们在语义上是不同的,但在功能上是相同的。

有关详情,请参阅此Stack Overflow讨论。

Difference Between *(Pointer + Index) and Pointer[]

答案 4 :(得分:1)

当您想要一个简单的答案时,使用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时,它的平均值就是类型的sizeof。

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

因此:

*(*(a + 3) + 4) == a[3][4] 

答案 5 :(得分:-2)

你得到的输出是12,这是完全正确的。 你为数组的每个元素做了a[i][j] = i*j ;。现在打印*( *(a + 3) + 4),它与a[3][4]相同。正如您a[i][j] = i*j所做的那样,您现在拥有a[3][4] = 3*4 = 12。因此它将打印12