C语言数组

文章目录

嘿嘿,家人们,今天咱们来详细介绍下C语言中的数组,好啦,废话不多讲,开干!

1:一维数组的创建和初始化

概念:数组是指一组**相同类型元素**的集合。

从这个概念中,我们可以知道以下两个信息:

(1):数组中存放的是1个或多个数据,但是数组的元素个数不能为0。

(2):数组中存放的多个数据,其数据类型是相同的。

数组分为一维数组和多维数组,多维数组一般比较常见的是二维数组。

1.1 创建方式

type_t arr_name [const_n]

//type_t 指数组的元素类型

//const_n 为一个常量表达式用于指定数组的大小

//[]中的常量值是用于指定数组的大小,这个数组的大小要根据实际的需求来进行指定。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr1[5];
	int arr2[3 + 2];
	
	int n = 0;
	scanf("%d\n",&n);
	//变长数组
	char arr3[n];
	return 0;
}

PS:在创建数组时,我们通常使用一个常量表达式用于指定数组的大小,而不是变量,原因在于,在c99之前数组只能是常量指定大小,在C99之后引入了变长数组的概念,数组的大小是可以使用变量来指定滴。博主使用的vs2022是不支持变长数组滴,希望uu们注意。

1.2:一维数组的初始化

有时候,数组在创建的时候,我们需要给定一些初始值,这种操作就被称作初始化。那么如何对数组进行初始化呢?数组的初始化一般使用大括号,将数据放在大括号中。
c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	//完全初始化
	int arr1[5] = { 1,2,3,4,5 };

	//不完全初始化,第一个元素初始化为1,剩余的元素默认初始化为0
	int arr2[8] = { 1 };
	
	//未指定大小,则根据数组中元素的值来确定数组的元素个数
	int arr3[] ={1,2,3,4,5};
	
	//错误的初始化----初始化项太多,超过了数组的元素个数
	int arr4[3] = {1,2,3,4};
	return 0;
}

1.3:一维数组的使用

学习了⼀维数组的基本语法,⼀维数组可以存放数据,存放数据的⽬的是对数据的操作,那我们如何使⽤⼀维数组呢?
1.3.1:数组下标

C语言规定数组中的每个元素是有对应的下标的,下标是从0开始的,假设数组有n个元素,最后一个元素的下标识n-1,下标就相当于数组元素的标号。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	return 0;
}

在C语言中数组的访问提供了一个操作符[],这个操作符叫:下标引用操作符有了下标访问操作符,我们就可以轻松地访问到数组的元素了,譬如我们想访问下标为7的元素,就可以使用arr[7],访问下标为3的元素,可以使用arr[3]。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[7]);
	printf("%d\n", arr[3]);
	return 0;
}

1.4:一维数组在内存中的存储

有了前面的知识,我们其实使用数组基本上没有什么障碍了,如果想要深入了解数组,我们最好能了解一下数组在内存中的存储。 接下来我们将使用如下代码来打印数组在内存中的存储。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)
	{
		//%p用于打印指针的值,将地址以16进制的形式输出
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}
	return 0;
}

从输出的结果我们可以发现,数组随着下标的增长,地址是由小到大变化的,并且每两个相邻的元素之间相差4(因为一个整型占4个字节 )。因此,我们可以得出这样一个结论:数组在内存中是连续存储的,并且随着下标的增长,地址是由低到高变化的,从低地址到高地址

2:二维数组的创建和初始化

概念:前面博主所讲的数组被称作一维数组,数组的元素类型都是内置类型的,如果我们把一维数组作为数组的元素,这个时候为**二维数组**,二维数组作为数组元素的数组被称为**三维数组**,二维数组以上的数组统称为**多维数组**。

PS:二维数组可以与我们在大学中线性代数中的矩阵进行类比哦

2.1:二维数组的创建

type arr_name[常量值1][常量值2]

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	//3表示数组有3行,5表示每一行有5个元素,即3行5列
	int arr1[3][5];
	double arr2[2][8];
	return 0;
}

2.2:二维数组的初始化

二维数组的初始化,和一维数组一样,也是使用大括号初始化滴!
c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	//不完全初始化
	int arr1[3][5] = { 1,2 };
	int arr2[3][5] = { 0 };

	//完全初始化
	int arr3[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
	return 0;
}

ps:二维数组在初始化时,行可以省略,但是列不能够省略,当行省略时,则是根据数组中的元素的值来确定行。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{

	int arr1[][5] = { 1,2,3 };
	int arr2[][5] = { 1,2,3,4,5,6 };


	int arr3[][5] = { {1,2},{3,4},{5,6} };
	return 0;
}

2.3:二维数组的下标

当我们掌握了二维数组的创建与初始化后,那我们怎么样去使用二维数组呢?其实二维数组的访问也是通过下标的形式去访问的,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。
C语言规定,二维数组的行是从0开始的,列也是从0开始的。

通过这段代码实现了对二维数组的访问,只要我们能够按照一定的规定产生所有的行和列,就能够实现对二维数组的访问。

2.4:二维数组在内存中的存储

和一维数组一样,如果想研究二维数组在内存中的存储方式,我们也是可以打印出数组所有元素的地址滴。
c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };

	//锁定行
	for (int i = 0; i < 3; i++)
	{
		//锁定列
		for (int j = 0; j < 5; j++)
		{
			printf("&arr[%d][%d] = %p ",i,j,&arr[i][j]);
			printf("\n");
		}
		printf("\n");
	}
	
	return 0;
}

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

3:数组越界

数组的下标是有范围限制的。

数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。

因此数组的下标如果小于0,或者大于n-1 ,就是数组越界访问了,超出了数组的合法空间的访问。
ps:C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。

因此在写代码时,最好自己做越界的检查。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5 };

	for (int i = 0; i <= 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

4:数组名

什么是数组名呢?博主将通过下面这段代码来讲解数组名
c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5 };
	printf("  arr   = %p\n", arr);
	printf("&arr[0] = %p\n", &arr[0]);
	printf(" *arr   = %d\n", *arr);
	return 0;
}

通过这段代码的运行结果我们可以得出,数组名表示数组首元素的地址。OK,如果数组名为首元素的地址,那么再看下面这段代码。

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5 };
	printf("%d\n", sizeof(arr));
	return 0;
}

不是说数组名为首元素的地址吗,那这里为什么输出的是40呢?
> 补充:(1):sizeof(数组名),计算的是整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
(2):&数组名,取出的是整个数组的地址。&数组名,数组名表示整个数组。
除了这两种特殊情况,在其他情况,所有的数组名均表示数组首元素的地址。

5:冒泡排序

有了我们数组以及函数等等的相关知识,接下来博主将为uu们介绍一种排序算法----->冒泡排序。这里博主以排成升序为例。

核心思想:两两相邻元素进行比较。

我们通过上面的动图可以发现,每进行一趟冒泡排序,就可以让元素到达自己应该处的位置。假设我们要对10个数进行排序,那么应该要进行几趟冒泡排序呢?答案应该是9趟,因为单独的一个数我们可以认为它是有序滴,这里家人们要注意哈。首先我们来看单趟的冒泡排序

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	//求出数组中的元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int j = 0; j < sz - 1; j++)
	{
		if (arr[j] > arr[j + 1])
		{
			int tmp = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = tmp;
		} 
	}
	return 0;
}

如果左边的元素大于右边的元素,那么这两个数就进行交换,直到该元素到达自己应该所处的位置,这是一趟冒泡排序,但是这里有10个数呀,要进行9趟冒泡排序,并且每次进行一趟冒泡排序后,趟数要减少,因此就要使用双层的嵌套循环来进行实现!

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	//求出数组中的元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:>");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	//确定总趟数
	for (int i = 0; i < sz - 1; i++)
	{
		//每进行一次冒泡排序,趟数要减少,因此- i
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	printf("\n");
	printf("排序后:>");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}
好啦,家人们,关数组这块的相关细节知识,博主就讲到这里了,如果uu们觉得博主讲的不错的话,请动动你们滴滴给博主点个赞,你们滴鼓励将成为博主源源不断滴动力!
相关推荐
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
ChoSeitaku7 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
DdddJMs__1357 小时前
C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
c语言·leetcode·题解
娃娃丢没有坏心思7 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
ahadee9 小时前
蓝桥杯每日真题 - 第11天
c语言·vscode·算法·蓝桥杯
No0d1es10 小时前
2024年9月青少年软件编程(C语言/C++)等级考试试卷(九级)
c语言·数据结构·c++·算法·青少年编程·电子学会
Che3rry10 小时前
C/C++|关于“子线程在堆中创建了资源但在资源未释放的情况下异常退出或挂掉”如何避免?
c语言·c++
kuiini12 小时前
C 语言学习-02【编程习惯】
c语言·学习
木辛木辛子12 小时前
L2-2 十二进制字符串转换成十进制整数
c语言·开发语言·数据结构·c++·算法