3

我对编程比较陌生,所以当有人建议构建一个结构数组(每个结构包含特定“项目”的 n 个属性)比构建 n 个属性数组更快时,我发现我对数组的了解不够以一种或另一种方式争论。

我读到这个:

数组如何在 C/C++ 中内部工作

基本数组教程

但我仍然不明白 C 程序如何通过索引从数组中检索特定值。

很明显,数组的数据元素在内存中相邻存储,并且数组名称指向第一个元素。

C 程序是否足够聪明,可以根据数据类型和索引进行算术运算以找出目标数据的确切内存地址,或者程序是否必须以某种方式在每个中间数据块到达那里之前对其进行迭代(如在链表数据结构)?

更根本的是,如果一个程序通过它的内存地址请求一条信息,机器是如何找到它的?

4

3 回答 3

7

让我们举一个更简单的例子。假设您有一个int test[10]像这样存储在地址 1000 的数组:

1|2|3|4|5|6|7|8|9|10

编译器知道,例如,一个 int 是 4 个字节。数组访问公式是这样的:

baseaddr + sizeof(type) * 索引

结构的大小只是其元素大小加上编译器添加的任何填充的总和。所以这个结构的大小:

struct test {
  int i;
  char c;
}

可能是 5。也可能不是,因为填充。

至于你的最后一个问题,很快(这很复杂)MMU 使用页表将虚拟地址转换为物理地址,然后请求物理地址,如果它在缓存中,则返回,否则从 main记忆。

于 2014-02-11T01:43:35.510 回答
2

你写了:

C 程序是否足够聪明,可以根据数据类型和索引进行算术运算以找出目标数据的确切内存地址

是的,这正是他们所做的。它们不会遍历中间项目(这样做无济于事,因为没有标记来指导每个项目的开始和结束)。

于 2014-02-11T01:39:03.960 回答
2

所以这就是整个技巧,数组元素在内存中是相邻的。

例如,当您声明一个数组时:int A[10];
变量A是指向数组中第一个元素的指针。

现在是索引部分,每当你这样做时A[i],就好像你在做*(A+i).

索引只是数组起始地址的偏移量,还要记住,在指针算术中,偏移量乘以数组数据类型的大小。

为了更好地理解这一点,请编写一些代码,声明一个数组并打印它的地址,然后打印数组中每个元素的地址。并注意偏移量如何始终相同并且等于机器上数组数据类型的大小。

于 2014-02-11T01:51:48.100 回答