目录
1、 什么是数组
所谓数组,就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。在c语言中数组属于构造数据类型。它的特点是:数组内部的元素都是同一种数据类型,可以是int,char,指针以及其他构造数据类型。
2、定义
定义格式:类型名 数组名[数组容量];
例如:
/** 一个班有30个人,需要定义一个整型数组来存放他们的学号 */
int number[30]; /** 其中 int:数据类型, number: 数组名,30: 数组容量 */
3、 初始化,访问以及遍历
a. 定义时初始化
格式:类型名 数组名[数组容量] = {数组元素/0};
解释:其前面部分和上面的定义格式是一样的,这里就不再累述,只是需要注意一点,‘数组容量’在这里是可选的,然后在’=’右边的花括号里面就是初始化数组的具体内容。
例如:
/**和初始化格式描述的完全一样的方式,其中int:类型,a:数组名,3:数组容量,{...}:初始化元素 */
int a[3] = {0,1,2};
int b[3] = {0}; /**将所有数组元素初始化为 0 */
/** 省略数组容量的定义和初始化方式,注意:这里如果像数组b一样初始化,就表示数组容量为 1 */
int c[] = {0,1,2};
数组的内存布局为(假想地址,非真实地址):
int a[3];
地址 | 元素 |
---|---|
0x800 | a[0] |
0x804 | a[1] |
0x808 | a[2] |
其布局是线性的,因为元素是int类型,所以每个元素暂用4个字节。
这里说的都是一维数组的情况,而c语言中还有多维数组,以二维数组为例(更高维数组就可以以此类推),其定义和初始化的格式为:
类型名 数组名[行数][列数];
类型名 数组名[行数][列数] = {{第一行元素}, {第二行元素},…{第n行元素}} 或者 {0};
注意:这里和一维数组有定义和初始化很相似,但是在二维数组定义并初始化时,行数可以省略,但列数却不能省略。其实在c语言中的多维数组在本质上仍然是一维数组(都是线性的),比如这个二维数组,就可以看做是由 ‘行数’个元素组成的一维数组,而这个元素又是一个有‘列数’个元素的一维数组,由于数组的特点是,所有元素都要是同一种数据类型,所以这个‘列数’必须要有,这样才能保证所有元素都是一样的,如果省略,那就会由{…}内填充的数据来决定,而数组在定义的时候,需要知道每个元素大小,以此来分配存储空间,如果省略了‘列数’,编译器就不知道其大小,就无法进行存储空间的分配。
例如:
/**
* 固定行数的定义和初始化方式
* int: 类型名,
* a: 数组名,
* 2: 行数
* 3: 列数
* {{...},{...}}:初始化元素
* 花括号里面, 1: a[0][0],第一行,第一列
* 3: a[0][2],第一行,第三列
* 4: a[1][0],第二行,第一列
*/
int a[2][3] = {{1,2,3}, {4,5,6}};
/** 同上,只是将所有元素都初始化为 0 */
int b[2][3] = {0};
/** 省略‘行数’的定义和初始化方式 */
int c[][3] = {{1,2,3}, {4,5,6}};
b. 访问及遍历
c语言中的数组在底层其实都是使用指针实现的,而且c语言规定:数组名是一个指向数组元素类型的指针,它是指向该数组的第一个(即下标值为零的第0号)元素的指针常量。所以c语言的数组就有两种访问方式:
- 使用下标运算符 [] + 下标 进行访问,形如:数组名[下标]
- 使用取内容运算符 *,形如: *(数组名 + 下标)
注意:c语言数组的下标是从 0 开始的
例如:
int a[3] = {1,2,3}; /** 定义一个拥有三个元素的素组 */
/** 访问第二个元素 */
//使用下标运算符 + 下标的方式
int i = a[1]; //获取第二个元素的值
a[1] = 5; //给第二个元素赋值
//使用取内容运算符 * 的方式
int j = *(a + 1); //获取第二个元素的值
*(a + 1) = 5; //给第二个元素赋值
数组的遍历就比较简单了:
- 可以简单是使用一个for循环,从下标 0 到 最大下标号(数组容量 - 1)的依次访问,形如:
void main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int i;
for (i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{/**
* sizeof(a) 获取数组总共占用的字节数,sizeof(a[0])获取一个元素占用的字节数,
* 二者相除就得到数组的元素数量
*/
printf("element number:%d, value:%d\n", i, a[i]);
}
}
- 使用函数递归的方式进行数组遍历,形如:
void array_foreach_recursive(int a[], int index)
{
if (index == 0)
{
return;
}
else
{
int i = index - 1;
array_foreach_recursive(a, i);
printf("element number:%d, value:%d\n", i, a[i]);
}
}
//在遍历的时候直接调用上面的函数,
void main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
array_foreach_recursive(a, sizeof(a)/sizeof(a[0]));
/**
* 注意,这里没有在遍历函数内部获取数组a的元素数量,是因为在c语言中,
* 数组作为函数参数的时候,会自动退化为指针,也就是说,在
* array_foreach_recursive函数中使用sizeof(a)得到的不是数组占用的字节数,而是得到
* 指针占用的字节数,在32bit的系统上是 4 字节,在64bit的系统上是8字节。
*/
}