我写了以下代码:
#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上的工作原理相同。为什么这样做,是否有这种行为的官方文档?
答案 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讨论。
答案 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
。