1、数组的概念
假设我们要创建10个变量,那就写10个变量,那问题来了,如果是100个变量呢?你是不是要创建100个变量,很麻烦;我们想这个10个,100个变量都是int类型,那我们能不能把它们放在一起呢?
我们把多个相同类型的变量集合放在一起,我们可以称之为数组;
数组是一组相同类型元素的集合;那我们能得到两条信息:
1、数组是有1个或者多个数据,数组的元素个数不能为0;
2、数组的元素类型是相同的
数组可以分为一维数组、二维数组、多维数组;
2、一维数组的创建和初始化
2.1 数组创建
type arr_name [常量值];
type;表示数组存放数据的类型;比如int、char、float
arr_name;表示数组名,数组名可以自己来写,尽量写有意义的数组名;
[ ] ;里面的常量值表示这个数组的大小,数组的元素个数;
存放在数组里面的值我们称为数组的元素,我们可以通过改变type和常量值的大小,指定数组元素的类型和数组的大小;
/*
比如存放20个数学成绩
int math[20];
10个浮点数
float ch[10];
10个字符
char a[10];
*/
2.2一维数组初始化
比如我们创建变量的同时,给它赋值,叫做初始化;
数组创建的同时,我们也给数组赋值,叫数组初始化;
数组我们要用{ }括号把元素装起来,元素之间要用英文逗号隔开;
不完全初始化
int arr[10]={1,2,3,4,5};
错误初始化
本来是存放5个元素,现在存放了7个元素
int arr[5]={1,2,3,4,5,6,7};
完全初始化
int arr[10]={1,2,3,4,5,6,7,8,9,10};
省略数组元素个数的初始化
int arr[]={1,2,3,4,5};
初始化可以省略数组大小,由编译器根据后面的内容帮你计算数组的元素个数
2.3一维数组的数组类型
比如一个变量
int a = 0;
变量a的类型就是int
如果是一个数组
int a[10];
那数组a的类型是int [10];
去掉变量名就是变量的类型
去掉数组名就是数组的类型
比如
int a[5]; 数组类型int [5]
float b[6]; 数组类型float [6]
char c[9]; 数组类型char [9]
3、数组的使用
既然创建了数组,那我们就要运用数组,那么搜首先我们来了解一下数组的小标。
3.1数组小标
数组的每个元素都对应这一个下标,下标从0开始,如果数组有n个元素,那么数组就有n-1个元素下标;
每个元素都有对应下标;比如你去找一个人,你需要找到对应的房间编号;才能找到那个人;对应的你找的下标,那么你就找到了那个元素;
我们可以运用[ ]--下标引用操作符,来找到对应下标的元素;
#include<stdio.h>
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
//打印 7
printf("%d\n",a[6]);
return 0;
}
3.2数组元素打印
既然我们知道通过下标找到元素,那我们就可以把整个数组的元素打印出来;
小标都是从0开始的,0 1 2 3 4 5 6 7 8 9;比如产生10个下标,那我们可以用循环,产生10个下标,打印每个元素;
#include<stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0; i<10; i++) //产生0~9的下标
{
printf("%d ",arr[i]);
}
return 0;
}
3.3输入数组元素
我们知道找到下标可以打印元素,我们可以输入一个值,改变这个元素;你找到了下标,就等于你知道这个元素的房间编号;你知道的这块空间,那我们就可以往里面放东西;
int main()
{
int i = 0;
int arr[5] = { 1,2,3,4,5 };
arr[3] = 9; //改变数组arr[3]
for (i = 0; i < 5; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
我们想打印一样,循环,只是这次我们不打印,我们输入进去
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++) //产生0~9的下标
{
scanf("%d",&arr[i]); //输入数据
}
return 0;
}
4、一维数组在内存中的存储;
首先我们要了解内存;内存会划分为一个一个内存单元,单位是字节;每一个内存单元都有一个编号,编号就是地址;
那我们把每个数组元素的编号打印出来,要用到&---取地址符;%p打印
int main()
{
int arr1[8] = { 1,2,3,4,5,6,7,8 };
int i = 0;
for (i = 0; i < 8; i++)
{
printf("&arr1[%d]的地址是%p\n",i,&arr1[i]);
}
return 0;
}
打印出来的结果,我们改一下环境用X86,地址没那么长;
这是16进制的地址;可以看出来每个地址都是差4,D0~D4差4;D4~D8也差4,以此类推;接下去每个地址间都差4;
我们的数组每个元素都是int类型;占4个字节;假设每个字节都有一个编号;那么从第一个字节开始,第一个字节为0,剩下的 1 2 3 4 5 6 7 8 9 10 11;我们可以看图知道第一个元素跟第二个元素差4个字节,第二个元素跟第三个元素也差4个字节;那么看上面的地址,它们也差4个字节,那我们把地址和下面的图定义起来,假设第一个元素是0;第二个元素是1;放到下图;那么第一个元素的起始地址在字节0跟第二个元素的起始地址在字节4,那它们是不是也差4;
注意;我们就可以得出一个结论;一维数组的元素是连续存放的;
5、sizeof函数计算数组元素个数
比如这个例子;我们定义数组的元素个数是10;那么循环里面也是10;可以这样写,但是这样就写死了;你没换一次元素个数,下面循环也要跟着换;
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++) //产生0~9的下标
{
scanf("%d",&arr[i]); //输入数据
}
return 0;
}
这时候我们可以用sizeof函数; 我们用sizeof函数就出来arr数组的大小是40字节,因为arr数组有10元素,每个元素是int,4个字节,那就是40个字节,下一个我们求的是数组的一个元素arr[0],字节是4;那我们换算一下如果我们,用数组的总大小除以一个元素的大小就等于数组的元素个数;因为每个元素的类型都是一样的4个字节;
int main()
{
int arr[10] = {0};
printf("%d\n", sizeof(arr)); //40
printf("%d\n", sizeof(arr[0])); //4
return 0;
}
sizeof(arr)/sizeof(arr[0]),这样的话,你只需要该上面的数组元素大小,就不用该下面循环的代码了;
int main()
{
int i = 0;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]); //数组元素的个数
for (i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
}
5、二维数组的创建
5.1二维数组
一维数组是由一组相同数据类型元素的集合;由1个元素或者多个元素;二维数组则是由多个一维数组组成,由二维数组组成的数组叫三维数组,二维数组以上组成的数组叫多维数组;
5.2二维数组创建
type arr_name [常量值1][常量值2]
type表示二维数组每一个元素的数据类型
arr_name表示二维数组的数组名
[常量值1]表示二维数组的行有几个元素
[常量值2]表示二维数组的列有几个元素
int arr[3][5]; //表示有3行,每一行5个元素
5.3二维数组初始化
//完全初始化
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
//不完全初始化
int arr[3][5] = {1,2};
完全初始化
不完全初始化
按行初始化,二维数组是由多个一维数组成元素组成的;一行是一个一维数组,那么一维数组我们用{ }括号括起来,二维数组也用{ }括号括起来;那就是第一个初始化第一行,第二个初始化第二行,第三个初始化第三行;
int arr [3][5] = {{1,2},{3,4},{5,6}};
省略行初始化;不能省略列
省略了列,就不知道每一行多少个元素,比如有5列,每一行存5个元素,那么第六个元素就自动到下一行了;自动计算行;
int arr[][5] = {1,2,3,4,5,6}; //每列5个元素
剩下的元素默认为0;
6、二维数组的使用
6.1二维数组下标
二维数组跟一维数组是一样有下标的,有行下标,有列下标,要找到二维数组的元素就要包含行下标,列下标;行下标跟列下标都是从0开始的;
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
打印元素7,行2,列4
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
printf("%d\n",arr[2][4]);
return 0;
}
6.2数组的打印和输入
跟一维数组一样,遍历每个下标,打印对应的元素;
第一行0,列 1,2,3,4,5
第二行1,列 2,3,4,5,6
第三行2,列 3,4,5,6,7
int main()
{
int i = 0;
int j = 0;
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
for (i = 0; i < 3; i++) //行
{
for (j = 0; j < 5; j++) //列
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}
输入也是一样的,遍历元素下标,输入值;
int main()
{
int i = 0;
int j = 0;
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
for (i = 0; i < 3; i++) //行
{
for (j = 0; j < 5; j++) //列
{
scanf("%d",&arr[i][j]);
}
printf("\n");
}
return 0;
}
7、二维数组在内存中的存储
首先我们看一下二维数组的地址
可以看到第一行的一位数组每个地址之间差4,第二行每个地址之间差4,每行是一个一位数组,它们是连续存放的,那第一行和第二行之间也差4,那只有是连续的才差4个字节;
那么它其实是这样存放的;
另一个视角
二维数组,它的每一行都可以看作成是一个一维数组;那么可以通过每一行的元素下标找到;
既然每一行是一个一维数组,那它的数组名是什么?
int arr[5] = {0};
arr 是数组名
arr[6] 数组名+下标
通过上面两张图,得出二维数组的第一行是通过arr[0]+元素下标找数组元素,那么第一行的数组名是arr[0];,第二行的数组名的arr[1];以此类推;
8、C99变长数组
我们在创建数组的时候,就把数组的大小写上去,数组大小就写死了,我们想自己输入一个值,指定数组的大小,在C语言的C99标准中,通过变量来指定数组大小;
int arr[a];
int arr1[c];
上面的数组的大小是有变量来决定的
注意变长数组是不能初始化的,因为变长数组的大小是运行时才决定的,给它初始化的时候,并不知道这个数组的大小,要存放多少个元素;只有在运行时才知道;
变长数组,并不是数组时变化的,是靠变量来指定数组的大小,一定指定,是不会改变的,要等下一次运行的时候,才会改变;
感谢观看!感谢指正!