基本魔法语言数组 (二) (C语言)


🌊用有趣的言语来阐述苦涩难懂的代码世界,让每一个技术都充满风趣!

🔭个人主页: 散峰而望

🚀学习方向: 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操作符如何精确每个魔法容器的尺寸...

数组教会我们不仅是技术,更是一种思维方式---将复杂问题分解为有序元素,用索引而非重复来管理数据。

愿数组的力量与你同在!

相关推荐
逻极7 小时前
Rust之结构体(Structs):构建自定义数据类型
开发语言·后端·rust
小二·7 小时前
深入解析 Rust 并行迭代器:Rayon 库的原理与高性能实践
开发语言·算法·rust
四念处茫茫8 小时前
Rust:复合类型(元组、数组)
开发语言·后端·rust
l1t8 小时前
对luasql-duckdb PR的测试
c语言·数据库·单元测试·lua·duckdb
初见无风8 小时前
3.3 Lua代码中的协程
开发语言·lua·lua5.4
数字芯片实验室8 小时前
流片可以失败,但人心的账本不能亏空
java·开发语言
l1t8 小时前
利用DeepSeek辅助改写luadbi-duckdb支持日期和时间戳数据类型
c语言·数据库·人工智能·junit·lua·duckdb·deepseek
彩妙不是菜喵8 小时前
初学C++:函数大转变:缺省参数与函数重载
开发语言·c++
逻极8 小时前
Rust 结构体方法(Methods):为数据附加行为
开发语言·后端·rust