目录
前言1、一维数组1.1、一维数组的创建和初始化1.2、一维数组的使用1.3、一维数组在内存中的存储 2、二维数组2.1、二维数组的创建和初始化2.2、二维数组的使用2.3、二维数组在内存中的存储 3、sizeof计算数组元素个数4、冷门小知识——C99中的变长数组总结——数组的特点:
前言
思考题:
一个养鸡场有6只鸡,他们的体重分别是1kg, 3kg, 5kg, 3.4kg,6kg,2kg,请问这6只鸡的总体重是多少?平均体重是多少?
思路分析:
用传统方法:
定义6个double 变量 //但是如果一个养鸡场有600只鸡呢?统计他们的和,求出平均值传统的方案不灵活,不能完成数量较大的需求用数组就会很方便:
数组可以存放多个同一类型的数据,是构造类型,传递是以引用的方式传递(即传递的是地址)
1、一维数组
1.1、一维数组的创建和初始化
存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。
例如:
//代码示例:int math[20];char ch[8];double score[10];
有时候,数组在创建的时候,我们需要给定一些初始值,此时就需要对其进行初始化。数组的初始化一般使用大括号,将数据放在大括号中。
另外
我们需要知道的是数组也是有类型的,数组算是一种自定义类型
。判断方法就是去掉数组名,留下的就是数组类型。
例如:
int arr1[10]; //arr1数组的类型是int [10];int arr2[12]; //arr2数组的类型是int [12];char ch[5]; //ch数组的类型是char [5];
arr1数组的类型是int [10];
arr2数组的类型是int [12];
ch数组的类型是char [5];
1.2、一维数组的使用
我们掌握了一维数组的基本语法后,接下来就要去学习如何去使用数组。
数组下标
C语言规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后一个元素的下标则为n-1。下标就相当于数组元素的编号
。
例如:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
画图理解:
在C语言中为数组的访问提供了一个操作符[ ](下标引用操作符)
。
我们使用这个下标引用操作符就可以轻松的访问到数组的元素。比如我们访问下标为4的元素,就可以去使用arr[4]
,得到数组元素5
了。
程序验证:
上面是访问单个数组元素并打印的方式,那如果我们想要
打印多个数组元素,该怎么办?其实也很简单,就是使用循环,去访问数组的下标就行了。
明白了数组的访问,当然我们也需要更加实际情况,自己给数组
输入
想要的数据,依然是使用数组下标和循环结构去实现。
代码实现:
#include<stdio.h>int main(){int arr[10] = { 0 };for (int i = 0; i < 10; i++){scanf("%d", &arr[i]);//输入自己想要的元素。}//------------------------------------------------------for (int j = 0; j < 10; j++){scanf("%d", arr[j]);//打印数组中的所有元素。}return 0;}
1.3、一维数组在内存中的存储
数组在内存中是怎样存储的?请看下图分析!
通过VS的调试,我们可以看到,数组随着下标的增长,地址是由小到大变化的
,并且我们发现每两个相邻的元素之间相差4(因为一个整型是4个字节)。所以我们得出结论:数组在内存中是连续存放的
。
2、二维数组
我们学习了一维数组,我们知道数组的元素都是内置类型的,如果我们把一维数组作为数组的元素,这个时候就是二维数组,二维数组作为数组元素的数组被称为三维数组… …
2.1、二维数组的创建和初始化
二维数组的创建和初始化跟一维数组差不多。
type arr_name[常量值1][常量值2];例如:int arr[3][5]; //int表示数组的每个元素都是整型,3表示数组有3行,5表示每一行有5个元素char ch[2][8]; //同理
①不完全初始化:
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};
③按照行初始化:
int arr4[3][5]={{1,2},{3,4},{5,6}};
④初始化时可以省略行,但不能省略列:
int arr5[][5]={1,2,3};int arr6[][5]={1,2,3,4,5,6,7};int arr7[][5]={{1,2},{3,4},{5,6}};
2.2、二维数组的使用
二维数组访问也是使用下标形式的,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。同样C语言规定,二维数组的行是从0开始的,列也是从0开始的。
对于二维数组的输入和输出,我们只需要能够按照一定的规律产生所有的行和列的数字,就可以实现对二维数组的输入和输出了。因此,我们同样可以借组循环实现生成数组的下标。
#include<stdio.h>int main(){int arr[3][5] = { 0 };int i = 0;//输入for (i = 0; i < 3; i++)//产生行号{int j = 0;for (j = 0; j < 5; j++)//产生列号{scanf("%d", &arr[i][j]);//输入数据}}//输出for (i = 0; i < 3; i++)//产生行号{int j = 0;for (j = 0; j < 5; j++)//产生列号{printf("%d ", arr[i][j]);//输出数据}printf("\n");}return 0;}
2.3、二维数组在内存中的存储
从数据存储在内存中的结果来看,我们可以看到每一行内部的每个元素都是相邻的,地址之间相差4个字节,跨行位置处的两个元素之间也是差4个字节,所以我们可以得出结论二维数组中的每个元素都是连续存放的
。
如图所示:
3、sizeof计算数组元素个数
sizeof
是C语言中的一个关键字,是可以计算类型或者变量大小的,它也可以计算数组的大小。
例如:
int arr[10]={0};printf("%d\n",sizeof(arr));//结果为40字节
理解
:arr数组中存放有10个元素,每个元素都为int类型,而我们知道int类型大小为4个字节,因此数组arr的大小为4*10=40
,注意单位是字节
。
此外,我们又知道数组中的所有元素的类型都是相同的,那么只要计算出一个元素所占的字节个数,就可以算出数组的元素个数了。
int arr[10]={0];int sz = sizeof(arr)/sizeof(arr[0]);printf("%d\n",sz);//结果为10
理解
:用数组的总大小除以每个数组元素的大小,就可以算出数组中的元素个数了,一般习惯直接用arr[0]来算,当然也可以用其他的元素,结果都是一样的。
总结:
sizeof()
操作符用于取长度,以字节为单位。sizeof(数组名)
即求的是整个数组的大小。sizeof(首元素)
即求数组单个元素的大小,用0下标,是因为数组至少存在一个有效元素,所以0下标永远存在。数组的大小可以用sizeof()计算得到。计算方式为sizeof(arr)/sizeof(arr[0])
。 4、冷门小知识——C99中的变长数组
在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量、常量表达式,或者是在初始化时省略数组大小。
例如:
int arr1[10];int arr2[3+5];int arr3[]={1,2,3};
由以上的例子我们发现,这样的语法限制,让我们创建的数组不够灵活,有时数组过大就浪费了空间,有时数组又太小不够用。
所以C99标准中给了一个变长数组的新特性,允许我们可以使用变量指定数组的大小。
例如:
int n=a+b;int arr[n];
数组arr就是变长数组,因为它的长度取决于变量n的值,编译器没法事先确定,只要运行时才知道n是多少。
变长数组的根本特性,就是数组长度只有运行时才能确定,所以变长数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定一个估计的长度,程序可以在运行时为数组分配精确的长度。但要注意一个容易迷惑的点,就是变长数组的意思是数组的大小是可以使用变量来指定,在程序运行的时候,根据变量的大小来指定数组的元素个数,而不是说数组的大小是可变的。
数组的大小一旦确定就不能再改变了
。