C语言数组的内存布局与访问方式小结
学习目标与重点学习目标理解C语言数组的内存布局掌握数组元素的访问方式学会使用指针访问数组元素避免因数组访问不当导致的错误学习重点数组的内存布局与存储方式数组元素的访问方法指针与数组的关系数组访问不当导致的错误二、数组的内存布局2.1 什么是数组数组是一种数据结构用于存储相同类型的多个元素。数组中的元素在内存中连续存储每个元素占用相同大小的内存空间。2.2 一维数组的内存布局一维数组的内存布局是连续的数组的第一个元素存储在最低地址最后一个元素存储在最高地址。示例12345678910111213#include stdio.hintmain() {intarr[5] {1, 2, 3, 4, 5};printf(数组第一个元素的地址%p\n, arr[0]);printf(数组第二个元素的地址%p\n, arr[1]);printf(数组第三个元素的地址%p\n, arr[2]);printf(数组第四个元素的地址%p\n, arr[3]);printf(数组第五个元素的地址%p\n, arr[4]);return0;}执行结果数组第一个元素的地址0x7ffccb8a8a50数组第二个元素的地址0x7ffccb8a8a54数组第三个元素的地址0x7ffccb8a8a58数组第四个元素的地址0x7ffccb8a8a5c数组第五个元素的地址0x7ffccb8a8a60分析每个int类型的元素占用4字节的内存空间因此数组元素的地址依次递增4字节。2.3 二维数组的内存布局二维数组可以看作是一维数组的数组内存布局也是连续的。例如二维数组int arr[2][3]可以看作是两个一维数组每个一维数组包含3个int类型的元素。示例1234567891011121314151617#include stdio.hintmain() {intarr[2][3] {{1, 2, 3}, {4, 5, 6}};printf(二维数组的地址%p\n, arr);printf(第一行数组的地址%p\n, arr[0]);printf(第二行数组的地址%p\n, arr[1]);printf(第一行第一个元素的地址%p\n, arr[0][0]);printf(第一行第二个元素的地址%p\n, arr[0][1]);printf(第一行第三个元素的地址%p\n, arr[0][2]);printf(第二行第一个元素的地址%p\n, arr[1][0]);printf(第二行第二个元素的地址%p\n, arr[1][1]);printf(第二行第三个元素的地址%p\n, arr[1][2]);return0;}执行结果二维数组的地址0x7fffd9a8a6a0第一行数组的地址0x7fffd9a8a6a0第二行数组的地址0x7fffd9a8a6ac第一行第一个元素的地址0x7fffd9a8a6a0第一行第二个元素的地址0x7fffd9a8a6a4第一行第三个元素的地址0x7fffd9a8a6a8第二行第一个元素的地址0x7fffd9a8a6ac第二行第二个元素的地址0x7fffd9a8a6b0第二行第三个元素的地址0x7fffd9a8a6b4分析二维数组的内存布局是连续的第一行数组的地址与二维数组的地址相同第二行数组的地址比第一行数组的地址高12字节3个int元素每个4字节。2.4 多维数组的内存布局多维数组的内存布局可以看作是一维数组的嵌套内存空间连续存储。例如三维数组int arr[2][3][4]可以看作是两个二维数组每个二维数组包含3个一维数组每个一维数组包含4个int类型的元素。三、数组元素的访问方式3.1 数组下标访问数组元素可以通过数组下标访问数组下标的范围是从0到数组长度减1。示例12345678910111213#include stdio.hintmain() {intarr[5] {1, 2, 3, 4, 5};printf(arr[0] %d\n, arr[0]);printf(arr[1] %d\n, arr[1]);printf(arr[2] %d\n, arr[2]);printf(arr[3] %d\n, arr[3]);printf(arr[4] %d\n, arr[4]);return0;}执行结果arr[0] 1arr[1] 2arr[2] 3arr[3] 4arr[4] 53.2 指针访问数组名可以看作是数组第一个元素的指针因此可以通过指针访问数组元素。示例1234567891011121314#include stdio.hintmain() {intarr[5] {1, 2, 3, 4, 5};int*ptr arr;printf(ptr[0] %d\n, ptr[0]);printf(ptr[1] %d\n, ptr[1]);printf(ptr[2] %d\n, ptr[2]);printf(ptr[3] %d\n, ptr[3]);printf(ptr[4] %d\n, ptr[4]);return0;}执行结果ptr[0] 1ptr[1] 2ptr[2] 3ptr[3] 4ptr[4] 53.3 指针运算指针可以进行运算如加法、减法、比较等。指针运算的结果与指针所指向的类型有关。示例123456789101112#include stdio.hintmain() {intarr[5] {1, 2, 3, 4, 5};int*ptr arr;printf(ptr指向的地址%p\n, ptr);printf(ptr1指向的地址%p\n, ptr1);printf(ptr2指向的地址%p\n, ptr2);return0;}执行结果ptr指向的地址0x7fffd9a8a6a0ptr1指向的地址0x7fffd9a8a6a4ptr2指向的地址0x7fffd9a8a6a8分析指针每次加1地址递增4字节int类型的大小。四、指针与数组的关系4.1 数组名与指针数组名可以看作是数组第一个元素的指针但数组名是常量指针不能修改。示例12345678910#include stdio.hintmain() {intarr[5] {1, 2, 3, 4, 5};printf(数组名arr%p\n, arr);printf(数组第一个元素的地址%p\n, arr[0]);return0;}执行结果数组名arr0x7fffd9a8a6a0数组第一个元素的地址0x7fffd9a8a6a0分析数组名arr和数组第一个元素的地址arr[0]是相同的。4.2 指针数组与数组指针指针数组和数组指针是两种不同的数据类型指针数组是一个数组每个元素是指针。数组指针是一个指针指向一个数组。