前言:本篇文章,我们将对一维数组,和二维数组进行展开式的讲解,并进行实际应用。
目录
一.一维数组
1.一维数组的创建和初始化
(1)数组的创建
(2)数组的初始化
2.一维数组的使用
3.一维数组在内存中的存储
二.二维数组
1.二维数组的创建与初始化
(1)数组的创建
(2)数组的初始化
2.二维数组的使用
3.二维数组在内存中的存储
三.总结
一.一维数组
1.一维数组的创建和初始化
数组是一组相同类型元素的集合。
(1)数组的创建
创建方式:
type_t arr_name[const_n];
type_t 是数组的元素类型
[const_n] 是一个常量或常量表达式,用来指定数组的大小
例如我们创建int类型和char类型的数组:
int arr1[5];
int arr2[2+3];
char arr3[10];
[ ]内一定要是一个常量或者常量表达式。那么我们再来看一个数组创建:
int a = 5;
int arr[a];
上述数组的创建可以被允许吗???事实上这牵扯到C语言的版本问题。
在C99之前,数组的大小只能用常量指定,但是在C99之后引用了变长数组的概念,数组的大小便可以用变量来指定了。
但是博主现在所使用的VS2019,以及VS2022都是不支持变长数组的。
(2)数组的初始化
初始化是指,在数组创建的同时给数组输入一些合理的初始值。
int arr[5];//已知数组大小时,可以只创建而不初始化
int arr1[10] = {1,2,3};//不完全初始化,剩余元素默认初始化为0
int arr2[] = {1,2,3,4};//创建大小未知的数组时,必须初始化,默认大小为元素个数
int arr3[5] = {1,2,3,4,5};//规范初始化,元素个数与数组大小一致
char arr4[3] = {'a',98,'c'};//字符初始化要用单引号,如果给的是数字,则存在数组里的实际是数字所对应的ASCII码值所对应的字符,例如98对应字符'b',所以实际存进数组的是字符'b'。
char arr5[] = {'a','b','c'};//常规字符初始化,不满同样补0
char arr6[] = "abcdef";//直接输入字符串时,用双引号
如上,数组的初始化化有很多种方法,其中值得注意的是,arr5和arr6两种字符数组的初始化,其中arr5是单个字符的输入,arr6是字符串整体的输入,这样arr6便会比arr5多输入一个'\0'。
2.一维数组的使用
对数组的操作,则是通过下标引用操作符 '[ ]' 来实现。
如上图我们可以看到,数组中元素的实际顺序是从0开始的,也就是说,假如我们要操作数组的第5个元素,那就要用arr[4],而这个'4'我们则称为是数组元素的下标。
这里我们定义了一个char型的数组,char型数组也可以接收数字,只不过是想要打印出数字就必须用到'%d'。
如果我们想把数组的全部元素打印出来,只需要用到for循环:
循环打印数组元素时,这里有一个陷阱,那就是我们的循环变量'i'是数字元素的下标,而数组元素的下标是元素的实际顺序减1,所以这里的'i'要从0开始,并且到9结束,所以限制条件是i < 10,而不是i <= 10。否则就会打印出多余的错误的结果,造成数组越界。
同时我们也可以通过数组元素下标来对其值进行修改:
如上,我们将'5'改成'1'。
3.一维数组在内存中的存储
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
arr[4] = 1;
for (i = 0; i < 10; i++)
{
printf("&arr[%d] = %p\n",i,&arr[i]);
}
return 0;
}
这里给大家补充一个小知识点,当我们要打印一个数据所存放的地址时,要用到'%p'。
由此我们可以看出,随着数组下标的增长,元素的地址也在有规律的增长,每个地址直接相差4个字节,而这正是一个int型数据所占用的字节数。因此我们可以得出结论:
数组在内存中是连续存放的。
二.二维数组
二维数组与一维数组的区别并不大,下面我们就来具体介绍一下二维数组。
1.二维数组的创建与初始化
(1)数组的创建
int arr[3][4];
char arr[4][5];
double arr[5][6];
如果一维数组只是一条直线,那么二维数组就是一个矩形,第一个[]代表行,第二个[]代表列。
(2)数组的初始化
int arr[3][4] = {1,2,3,4,5,6,7};//不完全初始化,会根据行数列数依次填充,不满补0
int arr1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};//不规范初始化
int arr2[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};//规范初始化,每一行用一个大括号
int arr3[3][4] = {{1},{2,3},{4,5,6}};//不完全初始化,每一行空缺的位置补0
int arr4[][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};//省略行数初始化,会根据{}数来默认行数
int arr5[3][] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};//省略列数初始化,不允许,会报错
2.二维数组的使用
二维数组的使用同样是通过下标。
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
printf("%d", arr[2][3]);
return 0;
}
假如我们要打印这个二维数组的元素12,那么我们就要找到它所在的位置,如下图所示为2行3列
那么如果我们要遍历整个数组又该怎么办呢???
很简单,只需要用到嵌套循环便可:
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
用外层循环来控制行数,内层循环来控制列数,这样便可以轻松实现二维数组的遍历,如果我们希望打印出来的格式为3行,那么我们就要在内层循环结束时输出一个'\n'来换行。
3.二维数组在内存中的存储
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
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;
}
我们同一维数组一样来看看二维数组是怎么在内存中存储的:
我们能够看出,二维数组的元素存储在内存中也是连续的,每一行的末尾与下一行的开头相连。
事实确实如此,小伙伴们可不要理所当然的以为二维数组在内存中就是分行存放的,分行只是我们想象中的二维数组的具象化,但其实在内存中并不是。
二维数组的元素同样也是随着下标的增长,内存不断增加。
三.总结
数组的讲解到这里就要结束啦,喜欢博主文章的小伙伴们不要忘记一键三连哦!
我们下期再见!