一个C程序是如何从数组内部获取信息的?

3
我相对编程比较新,所以当有人建议使用结构体数组(每个结构体都包含特定“项”的n个属性)比建立n个属性数组更快时,我发现我不知道足够关于数组的知识来支持或反驳这种说法。
我读了这篇文章: 如何在C/C++中内部工作数组 还有 基本数组教程 但我仍然不太明白C程序如何通过索引从数组中检索特定值。
显然,数组的数据元素存储在内存中相邻的位置,并且数组名称指向第一个元素。
C程序是否足够聪明,根据数据类型和索引进行算术运算,以找出目标数据的确切内存地址,还是程序必须以某种方式遍历到达目标数据之前的每个中间数据(如链接列表数据结构)?
更基本的是,如果程序通过其内存地址请求信息,机器如何找到它?

编译器是由人编写的,而人足够聪明,可以处理数组算术运算。 - phuclv
很多关于内存访问的效率或低效性都与缓存友好性有关:https://dev59.com/eGQn5IYBdhLWcg3wn4NS - happydave
3个回答

7
让我们来看一个更简单的例子。假设你有一个数组int test [10],它在地址1000处存储如下:

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

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

baseaddr + sizeof(type) * index

结构体的大小就是其元素大小的总和加上编译器添加的任何填充。因此,这个结构体的大小为:
struct test {
  int i;
  char c;
}

可能是5。但由于填充的原因,也可能不是。

至于你最后一个问题,简单来说(这非常复杂),MMU使用页表将虚拟地址转换为物理地址,然后请求物理地址,如果它在缓存中,则返回,否则从主存中获取。


2
你写道:

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

是的,这正是它们所做的。 它们不会迭代遍历中间项(这样做也没有帮助,因为没有标记来指导每个项的开始和结束)。

那很有道理! - user2127595

2

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

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

现在来看索引部分,每当您执行A[i]时,就像执行*(A+i)一样。

索引只是到数组开头地址的偏移量,在指针算术中,请记住偏移量乘以数组数据类型的大小。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接