C语言--数组

一、数组的概念

数组就是一类相同类型数据类型的集合,用来存放多个数据。简单来说就是把许多相同类型的数放在一起。
数组分为一维数组多维数组,多维数组中我们比较常见和使用的就是二维数组
数组中的数据称为数组的元素,数组在创建时应制定数组的类型和大小

二、一维数组

2.1一维数组的创建和初始化

首先是创建,创建一维数组的基本形式如下:

type arr_name[n];
int  arr[10];

·type是指数组中存放的数据的类型,可以是int,char,double等等,规定了数组中所存放元素的类型
·arr_name是数组的名字,可以随便取,但是一定要有意义,不能与C语言中规定的名字相冲突
·放在[ ]中的n代表是任意正常数,限定数组的大小
例如:

char name[10];
int score[8];
double length[16];

注意: 数组也有类型

int a = 10;//int 是变量a的类型
//与a类似
int arr[10];//int [10]是数组arr的类型
char name[6];//char [6]是数组name的类型

如下图:
在这里插入图片描述

初始化
在数组创建的过程中,我们可能需要对数组元素进行给定初始值赋值,进行初始化,数组初始化又分为完全初始化和不完全初始化。
初始化要用大括号,将数组元素放在大括号里面。

完全初始化
完全初始化是指把数组中的每个元素都初始化赋值

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

不完全初始化

int arr2[60] = { 1, 2 ,3 ,4, 5 };//不完全初始化

不完全初始化就是只对个别数组赋值,剩下的数组元素默认为0
下图是调试时打开监视窗口,看到arr数组中元素的值

错误的初始化

int arr[4] = { 1, 2, 3, 4, 5 };//错误的初始化

应注意数组元素的个数不能大于规定值,不要越界

2.2 一维数组的使用

我们学会了一维数组的创建的初始化,那么如何去使用它呢?
在C语言中,规定数组是由下标的,下标从0开始,例如:

int arr[5] = { 1,2,3,4,5 };
//数组元素:1 2 3 4 5
//下标:   0 1 2 3 4

C语言中规定用[]对数组元素进行访问使用,[]叫做下标引用操作符
有了下标引用操作符就能很好的使用数组元素,比如arr[0] = 1,arr[4] = 5
在这里插入图片描述

有人会有疑问,难道数组元素只能一个一个打印吗?
当然不是,数组也可以一下打印完的,那就需要用到for循环了

#include <stdio.h>
int main()
{
	int arr[6] = { 1,2,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 6; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

结果:
在这里插入图片描述
既然数组能printf打印,那么也就能用scanf输入了,与输出一样,输入的时候也要用for循环输入
记得每个数字之间要空格间隔开哦

int main()
{
	int arr[6] = { 0 };
	int i = 0;
	printf("输入:\n");
	for (i = 0; i < 6; i++)
	{
		scanf("%d ", &arr[i]);
	}
	printf("\n");
	printf("输出:\n");
	for (i = 0; i < 6; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

结果:
在这里插入图片描述

2.3一维数组在内存中的存储

学习了以上知识后,相信你对一维数组有了一定了解,如果对数组进一步了解,就要学习一维数组在内存中是如何存储的
那就让我们打印数组各元素的地址看一下,如下图:
注:%p是专门用来打印地址的

int main()
{
	int arr[6] = { 1,2,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 6; i++)
	{
		printf("%p\n", &arr[i]);
	}
	return 0;
}

结果如下:
在这里插入图片描述
我们知道int类型的数据占用4个字节,从图中不难看出从arr[0]第一个数据到最后,每个元素存放在内存中的地址从小到大依次增加4,所以得出结论:
数组元素在内存中是连续存放的,并且随着数组下标的增长,地址由低到高变化。

补充1:sizeof计算数组元素个数

sizeof是C语言中的一个关键字,用来计算类型或者是变量大小的,也可以用来计算数组大小和数组元素个数。
sizeof计算结果用 %zd 打印
例如:

int main()
{
	int arr[6] = { 1,2,3 };
	printf("%zd\n", sizeof(arr));//计算数组大小
	printf("%zd\n", sizeof(arr[0]));//计算数组元素大小
	printf("%d\n", sizeof(arr) / sizeof(arr[0]));//计算数组元素个数
	return 0;
}

结果:
在这里插入图片描述

第一个打印的结果是24,是整个数组占用内存中的大小,单位是字节;

第二个打印的是4,一个元素占用内存中的大小,因为数组每个元素类型相同,都是int类型,所以占用内存空间一样都是4。

第三个打印的是6,是数组元素个数,整个数组的大小除上一个元素的大小,就是数组元素的个数,24 / 4 = 6。

那么有什么用处呢?

当我们用到数组元素个数的时候,例如利用for循环遍历数组的时候,就可以用(以数组arr为例)sizeof(arr)/ sizeof(arr[0])来替代,就不用把数组元素个数固定写死,因为这个值也是随之变化的

补充2:数组名的本质

1.数组名是数组首元素的地址
在这里插入图片描述
2.sizeof( )中的数组名,表示整个数组
上面在补充1中已经证明,不在过多解释。
3.&数组名,这里的数组名表示整个数组
在这里插入图片描述

地址默认以16进制打印
arr + 1 地址增大了4(一个数组元素的大小);
&arr[0] + 1地址增大了4(一个数组元素的大小);
&arr + 1地址增大了24(一个数组的大小);

三、二维数组

3.1.二维数组的创建和初始化

理解了一维数组的创建和初始化,二维数组就照葫芦画瓢就行
首先也是二维数组的创建,二维数组的创建形式如下:

type arr_name[n][m];

与一维数组相同,
type代表的是数组中元素的类型;
arr_name是数组的名字;
不同的是
既然是二维的,就像长方形一样,有它的长和宽。二维数组有它的行和列
放在 第一个[ ] 中的n是二维数组的 行数,放在 第二个[ ] 中的m是二维数组的列数
例如:

int age[5][6];
     //5行 6列
double score[3][3];
          //3行 3列

二维数组的初始化
与一维数组相同,二维数组初始化也用大括号 { } 初始化,将将想放入的数组元素依次放入括号中,在括号中的元素会依次初始化赋值给(假设数组名为arr)arr[0][1], arr[0][2]……当第一列放满了才开始进行第二行
初始化也分为完全初始化和不完全初始化
完全初始化

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

如下图:
在这里插入图片描述

不完全初始化

int arr[6][8] = { 1,2,3,4,5,6 };//不完全初始化

剩下的数组元素都默认为0,如下图:
在这里插入图片描述
但是只有当第一行初始化完了才能初始化第二行吗,回答是 NO!
二维数组可以按行展开,不过要将每一行的数字要再用一个 大括号{ } 包括在内,例如:

int arr[6][8] = { {1,2,3},{4,5,6} };
        //第一行元素是1 2 3 0……
        //第二行元素是4 5 6 0……

在这里插入图片描述
这样就可以按照每一行来初始化赋值了

老铁们,注意啦,二维数组还有一个非常重要的点
那就是二位数组在初始化时,行可以省略,但是列不可以省略,例如:

int a[][3] = { 1,2,3,4,5 };
//  行  列

在这里插入图片描述
了解了二维数组的创建和初始化后,我们就要来学习如何来使用二维数组了

3.2二维数组的使用

二维数组的访问

二维数组的使用也是用下标[ ]来访问使用的,但是既然是二维,所以要有两个[ ]来确定数组元素,一个确定数组元素所在行,一个确定所在列
与一维数组一样,二维数组的行和列也是从0依次开始增大的

int main()
{
	int a[3][4] = { 1,2,3,4, 5,6,7,8 ,9,10,11,12 };
	printf("%d", a[1][2]);
	return 0;
}

代码运行,打印第2行,第3列的7
在这里插入图片描述
我们知道了单个元素的访问,那么如何对整个二维数组输入和打印呢?

二维数组的输入和输出打印
二维数组输入和打印与一维数组相似,都要用到for循环,但与之不同的是,二维数组嘛,当然要用到两次for循环咯
先从第一行开始,打印第一行所有元素,接着第二行……
代码如下:

int main()
{
	int a[3][4] = { 0 };
	int i = 0, j = 0;
	printf("输入:\n");
	for (i = 0; i < 3; i++)//遍历行,产生行号
	{
		for (j = 0; j < 4; j++)//遍历列,产生列号,打印每一行的元素
		{
			scanf("%d", &a[i][j]);//二维数组输入
		}
	}
	printf("输出:\n");
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%d ", a[i][j]);//二维数组输出
		}
	}
	return 0;
}

结果:
在这里插入图片描述

3.3二维数组在内存中的存储

知道一维数组在内存中的存储情况,那么二维数组是什么样子的呢?
我们来打印一下二维数组各个元素的地址,如下:

int main()
{
	int arr[3][5] = { 0 };
	int i = 0, j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%p\n", &arr[i][j]);
		}
	}
	return 0;
}

结果:
在这里插入图片描述
由结果可知,二维数组在内存中也是连续存放的,一行存完紧接着存下一行,地址由低到高。

四、C99中的变长数组

在C99标准之前,数组的创建和初始化只能用常数或者是常量表达式,也可以省略数组大小直接初始化。
但是,这样创建数组就不够灵活,有可能数组过大浪费空间,也可能过小不够用
所以在C99中就引入了变长数组的概念,允许用变量来规定数组大小
例如:

int n = m + n;
int arr[n];

变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化,而且变长数组并不意味着数组的大小可随意变化,只是可以通过变量来规定数组大小,而不是说变长数组的大小是可变的,变长数组大小一旦被确定就无法改变。

#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	int arr[n];
	int i = 0;
	for (i = 0; i < n; i++)//对数组赋值
	{
		arr[i] = i;
	}
	for (i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);//打印数组
	}
	return 0;
}

但是在VS2019/2022上却不支持这种写法,这是在Dev上编译的代码
给n输入10,结果如下:
在这里插入图片描述

五、数组练习

1.二分查找法
2.冒泡排序法
后面博主会专门讲解这两个练习,记得关注我哦!
本人才疏德浅,文章肯定有许多不足和错误之处,还望众多码友包含和赐教,万分感谢!
在这里插入图片描述

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值