2

当您只使用一个下标访问二维数组时,有人可以向我解释 C 如何检索一行的正确内存地址吗?

例子 -

int array2D[2][2] = {1,2,3,4};
printf ( "starting address of row2 = %p" , array2D[1]);

我知道在 C 中下标时实际上发生的是指针添加,因此对于一维数组,数组名称指向元素 0。在这种情况下,如果我想要元素 1,编译器将采用起始地址(比如 4000)和向它添加 4(假设为 4 位 int),以便返回的是内存地址 4004 处的项目。

我的理解是,当您填充二维数组时,如我的示例所示,它们是按顺序分配的,所以我会有

1 2
3 4
在地址

4000 4004

4008 4012

那么 C 如何计算出在这种情况下 array2D[1] 应该指向 4008 而不是 4004?它是运行 sizeof() 运算符还是我在这里误解了基本原理?

提前致谢

4

4 回答 4

3

C 知道每行有多长,因此它会通过乘法来找到该行。

int x[][3] = {{1,2,3},{4,5,6}};

然后&x[1][0]&x[0][0]加号3 * sizeof(int)

这就是为什么在多维 C 数组声明中,必须指定除第一个维度之外的所有维度。

于 2012-08-24T15:29:52.503 回答
0

指针算法取决于所指向元素的类型。给定一个指向ptype的指针T,指向typep + 1的下一个元素T,不一定是下一个字节p。如果Tchar,则p + 1指向char之后的下一个对象p,该对象从紧随其后的字节开始p;如果Tchar [10],则p + 1指向after的下一个10 元素数组charp,该数组从 后面的第 10 个字节开始p

中的表达式 的类型array2d是“2-element array of 2-element array of int”,它“衰减”为类型“pointer to 2-element array of int”,或int (*)[2]1。因此,表达式array2d[1]被解释为*(array2d + 1)。由于array2d指向 类型的对象int [2],因此array2d + 1指向下一个 2 元素数组intfollowing array2d,它2 * sizeof intarray2d.


1. 除非它是sizeof或一元运算符的操作数&,或者是用于在声明中初始化另一个数组的字符串字面量,否则“N-element array of T”类型的表达式将转换为“pointer”类型的表达式to T" 并且它的值将是数组中第一个元素的地址。

于 2012-08-24T15:52:11.077 回答
0

这会有点啰嗦,但请耐心等待。

数组订阅只是一种简写:指针类型在所有上下文中都(p[N])等于(*(p + N))(尽管两者都是无效的表达式void*)。

现在,如果p是数组类型,它会在表达式中衰减为指针类型,例如(*(p + N)); anint[2][2]将衰减为类型的指针(*)[2](即指向 an 的指针int[2])。

指针算术将类型考虑在内;我们需要将事物转换char*为可视化编译器对我们所做的事情:

T *p;
p[N] equals *(p + N) equals *(T*)((unsigned char*)p + N * sizeof *p)

现在,如果T是一个int[2](等于我们上面描述的情况),那么sizeof *p就是sizeof(int[2]),即2 * sizeof(int)

这就是订阅在所谓的多维数组中的工作方式。

于 2012-08-24T15:52:23.647 回答
0

sizeof(array2D[1]) == 8;
如果array2D地址是4000;
所以 array2D[1] 地址是 4000+sizeof(array2D[1]) == 4000+8;

于 2012-08-24T16:08:51.173 回答