3. 一维数组的内存结构

要真正了解 C 语言,你要了解每一种类型的内存结构。这一节我们来介绍一下一维数组的内存结构。

以整数类型的一维数组为例,比如我们声明如下的数组:

int myarr[3] = {100, 200, 300};

我们通过 sizeof 运算符计算 sizeof(myarr) 得到数组占用的内存数是 12 个字节。那这三个整数又是如何排列的呢?

我们先来说结论。

  1. 数组的起始地址就是第一个数据元素的地址。
  2. 数组中每个数据元素的起始地址是:数组的起始地址 + 数据元素类型占用的字节数 * 索引

我们通过取地址运算符,对上述数组,以及数组中数据元素依次取地址,这样就可以得到每个数据在内存中的地址了。让我们一起来写程序验证吧。

示例程序

// filename: 1d_array_momory.c
#include <stdio.h>

int main(int argc, char *argv[]) {
    int myarr[3] = {100, 200, 300};

    printf("&myarr: %p\n", &myarr); // 获取数组的起始地址
    printf("&myarr[0]: %p\n", &myarr[0]); // 第一个数据元素的起始地址
    printf("&myarr[1]: %p\n", &myarr[1]); // 第二个数据元素的起始地址
    printf("&myarr[2]: %p\n", &myarr[2]); // 第三个数据元素的起始地址
    printf("&myarr[3]: %p\n", &myarr[3]); // 第三个数据元素的末尾地址

    return 0;
}

运行结果如下:

weimingze@mzstudio:~$ gcc -o 1d_array_momory 1d_array_momory.c
weimingze@mzstudio:~$ ./1d_array_momory
&myarr: 0x7ffdde2519dc
&myarr[0]: 0x7ffdde2519dc
&myarr[1]: 0x7ffdde2519e0
&myarr[2]: 0x7ffdde2519e4
&myarr[3]: 0x7ffdde2519e8

由此可见, 数组 myaddr 的内存结构如下图所示

           myarr[0]            myarr[1]            myarr[2]
----+----+----+----+----+----+----+----+----+----+----+----+----+----
... |        100        |        200        |        300        | ...
----+----+----+----+----+----+----+----+----+----+----+----+----+----
    ^                   ^                   ^                   ^
    | &myarr[0]         | &myarr[1]         | &myarr[2]         | &myarr[3]
    | &myarr            |                   |                   |
0x7ffdde2519dc    0x7ffdde2519e0      0x7ffdde2519e4      0x7ffdde2519e8
(数组的起始地址)

练习:

声明一个 double 类型的数组,通过打印地址的方式来分析数组的内存结构并在纸上画图说明。