
🌊用有趣的言语来阐述苦涩难懂的代码世界,让每一个技术都充满风趣!
🔭个人主页: 散峰而望
🚀学习方向: C/C++等方向
📌专栏系列:
💬人生格言: 冀以尘雾之微,补益山海,荧烛末光,增辉岁月。
🎬博主简介



文章目录
- 前言
- [6. 二维数组的创建](#6. 二维数组的创建)
-
- [6.1 二维数组的概念](#6.1 二维数组的概念)
- [6.3 二维数组的创建](#6.3 二维数组的创建)
- [7. 二维数组的初始化](#7. 二维数组的初始化)
-
- [7.1 不完全初始化](#7.1 不完全初始化)
- [7.2 完全初始化](#7.2 完全初始化)
- [7.3 按照行初始化](#7.3 按照行初始化)
- [7.4 初始化时省略行,但是不省略列](#7.4 初始化时省略行,但是不省略列)
- [8. 二维数组的使用](#8. 二维数组的使用)
-
- [8.1 二维数组的下标](#8.1 二维数组的下标)
- [8.2 二维数组的输入和输出](#8.2 二维数组的输入和输出)
- 9.二维数组在内存中的存储
- [10. C99中的变长数组](#10. C99中的变长数组)
- [11. 三维数组](#11. 三维数组)
- 结语
前言
前一章我们具体了解了C语言中最为精妙和强大的存储艺术 -- 数组 !并且知道如何运用单排书架,整齐排列同类卷轴 的一维数组 ,接下来让我们来了解并掌握如同整个图书馆,构建行与列的魔法矩阵 的多维数组。
6. 二维数组的创建
6.1 二维数组的概念
前面学习的数组为一维数组,数组的元素都是内置类型的。如果我们把一维数组作为数组的元素,那么由一维数组组成的数组被称为二维数组 。同理,二维数组作为数组元素的数组称为三维数组 ,二维数组以上的数组统称为多维数组。

6.3 二维数组的创建
那我们如何定义二维数组呢?语法如下:
type arr_name[常量值1][常量值2]
| | | |
类型 数组名 行 列
例如:
c
int arr[3][5];
double date[6][8];
解释:上述代码中出现的信息
- 3(6)表示数组有3(6)行
- 5(8)表示数组有5(8)列
- int(double)表示数组的每个元素是整形(浮点型)元素
- arr(date)是数组名,可以根据自己的需要指定名字
7. 二维数组的初始化
在创建变量或者数组的时候,给定一些初始化,被称为初始化。
那二维数组如何初始化呢?像一维数组一样,也是大括号初始化。
7.1 不完全初始化
c
int arr1[3][4] = { 1,2 };
int arr2[3][4] = { 0 };
二维数组是逐行初始化,如果是不完全初始化,剩余的元素默认初始化为0。

7.2 完全初始化
c
int arr3[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };

7.3 按照行初始化
c
int arr4[3][4] = {{1,2},{3,4},{5,6}};

7.4 初始化时省略行,但是不省略列
c
int arr5[][4] = { 1,2,3 };
int arr6[][4] = { 1,2,3,4,5,6 };
int arr7[][4] = {{1,2},{3,4},{5,6}};

8. 二维数组的使用
8.1 二维数组的下标
当我们掌握了二维数组的创建和初始化,那么我们怎么使用二维数组呢?
其实二维数组访问也是使用下标的形式,二维数组是有行和列,就像找书文一样,只要锁定了行和列,就能锁定数组中的一个元素。
C语言中规定,二维数组的行和列都是从0开始的,如下所示:
c
int arr[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };

图中最右侧竖着一列数字表示行号,第一行数字表示列号,都是从0开始,比如:第1行,第2列,就能快速定位出4。
c
int main()
{
int arr[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };
printf("%d\n", arr[2][1]);
return 0;
}
输出结果如下:

8.2 二维数组的输入和输出
如何从一排书架中(二维数组)找到想要的(书籍)我们已经知道了,那如何访问整个二维数组呢?
其实我们只要按照一定的规律产生所有的行和列就行。以上面一段代码中的arr为例,行的选择范围是0 ~ 2,;列的取值范围是0 ~ 4,所以我们可以借助循环实现生成所有下标。
c
int main()
{
int arr[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };
int i = 0;//遍历行
//输出
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}

c
int main()
{
int arr[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };
int i = 0;//遍历行
//输入
for (i = 0; i < 3; i++)//产生行号
{
int j = 0;
for (j = 0; j < 4; j++)//产生列号
{
scanf("%d", &arr[i][j]);//输入数据
}
}
//输入
for (i = 0; i < 3; i++)//产生行号
{
int j = 0;
for (j = 0; j < 4; j++)//产生列号
{
printf("%d ", arr[i][j]);//输出数据
}
printf("\n");
}
return 0;
}

9.二维数组在内存中的存储
像一维数组一样,我们如果想研究二维数组在内存中的存储方式,我们也可以打印出相关的地址。
代码如下:
c
int main()
{
int arr[3][4] = { 0 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
}
}
return 0;
}
输出结果如下:

从输出结果来看,每一行内部的每一个元素都是相邻的,地址之间相差4个字节,跨行位置处的两个元素(如:arr[0][4]和arr[1][0])之间也是差4个字节,所以二维数组中的每个都是连续存放的。
如下图所示:

了解清楚二维数组在内存中的布局,有利于后期使用指针来访问数组的学习。
10. C99中的变长数组
在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量、常量表达式,或者如果我们初始化数据的话,可以省略数组大小。
如:
c
int arr1[10];
int arr2[3+5];
int arr3[] = {1,2,3};
虽然没有直接指定数组的大小,编译器会根据数组的初始化内容来确定一个数组的大小。
这样的语法限制,让我们创建数组就会不够灵活,有时候数组大了浪费空间,有时侯数组有小了不够用。
C99中给一个**变长数组(variable-length array,简称VLA)**的新特性,允许我们可以使用变量指定数组大小。
请看下面的代码:
c
int n = a + b;
int arr[n];
上面示例中,数组arr就是变长数组,因为它的长度取决于变量n的值,编译器没法事先确定,只有运行时才知道n是多少,所以变长数组不能初始化。
不过在vs 2022会面临无法编译问题,可以改一下编译器,右键单击解决方案 ,然后属性


之后可以测试一下
c
int main()
{
int n = 0;
scanf("%d", &n);
int arr[i];
int i = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
11. 三维数组
有开始可知,三维数组的元素类型是二维数组,同二维数组一般,可以带入一下。
代码如下:
c
int main()
{
int arr[3][4][2] = { {{1,1},{1,2},{1,3},{1,4}},{2,1,3,4,0,5},{{3,1},{0},{1},{2,4}} };
int i = 0;
int j = 0;
int k = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
for (k = 0; k < 2; k++)
{
printf("%3d ", arr[i][j][k]);
}
printf("\n");
}
printf("\n\n");
}
return 0;
}

剩下其他维度的数组可以类推得到。
结语
回顾这段旅程,我们见证了一维数组 如何将散落的魔法卷轴整齐归位,多维数组 如何建行列分明的魔法图书馆,sizeof操作符如何精确每个魔法容器的尺寸...
数组教会我们不仅是技术,更是一种思维方式---将复杂问题分解为有序元素,用索引而非重复来管理数据。
愿数组的力量与你同在!

