作者:zhj808008 | 来源:互联网 | 2023-10-11 23:37
文章目录1数组定义2一维数组2.1一维数组的定义2.2一维数组初始化2.3一维数组赋值2.4一维数组引用3二维数组3.1二维数组的定义3.2二维数组初始化4向函数传递数组4.1一维
文章目录
- 1 数组定义
- 2 一维数组
- 2.1 一维数组的定义
- 2.2 一维数组初始化
- 2.3 一维数组赋值
- 2.4 一维数组引用
- 3 二维数组
- 4 向函数传递数组
- 4.1 一维数组传递
- 4.2 二维数组传递
- 4.3 将数组名作为参数传递时
1 数组定义
数组是一组相同类型的数据的集合
数组中的元素通过下标来区分
一维数组:储存线性数据
二维数组:用来储存平面信息,
三维数组:储存空间信息或更复杂的时空信息。
2 一维数组
2.1 一维数组的定义
数组声明格式:
类型说明符 数组名[常量表达式]
类型说明符:除void以外的任何类型
定义数组大小,即元素个数。只允许字面常量或符号常量
,不允许是变量
int x[5];
// 或者
#define N 5
int x[N];
2.2 一维数组初始化
-
初始化方式
- 将数组中所有元素初始化为0(偷懒),事实上只给第一个元素赋了值
int a[10] = {0};
- 如果是赋予不同的值,用逗号分开即可
int x[5]={20, 4, 16, 37, 9};
- 对部分元素赋初值,长度不能省,其余自动初始化为0
int z[6]={13, 24, 9};
- 对全部元素赋初值时可以不指定数组长度。
double y[ ]={2.8, 10.4};
- c99增加一种特性,可以指定初始化元素
int a[10] = {[3] = 3, [5] = 5}
- 当数组声明为静态数组或全局数组时,系统会对所有数组元素自动初始化为0
static int a[5]
-
注意事项:
- 注意下标(比如数组长度为5,下标是0~4)
- 记得初始化,一定要先赋值再输出,不然
数组越界
,有时不会报错但会产生乱七八糟的东西
。
-
我们常需要用循环来访问数组
int main(void)
{
int a[5]; /*定义大小为5的数组*/
int index;
for(index = 0; index <5; index++)
{
printf("%d\n", a[index]);/*循环输出*/
}
return 0;
}
2.3 一维数组赋值
/* 定义大小为3的整型数组并初始化 */
int a[3] = {11, 22, 33};
a[1] = 100; /* 正确,a[1]赋值为100 */
a[3] = 200; /* 错误,下标越界 */
a[10] = 300; /* 错误,下标越界 */
2.4 一维数组引用
数组名[下标表达式]
下标表达式必须是整数,且大于等于0;
数组名代表数组首地址
,对数组不能整体输入和输出。
3 二维数组
3.1 二维数组的定义
二维数组的定义:
以二维表形式存储数据。(行、列概念)
类型说明符 数组名[常量表达式][常量表达式]
行数(第一维)列数(第二维)
例如: float a[3][4];
二维数组在内存中按行存储
3.2 二维数组初始化
- 按行存取
int b[2][3]={{1,2,3},{4,5,6}};
或者
也可写成:int b[2][3]={1,2,3,4,5,6}; (按数组排列顺序对各元素赋初值)
- 对部分元素赋初值
int b[3][2]={0};//全部元素初始化为0
int a[2][4]={ {1},{5} }; //注意赋值里是2行的意思,实际两行的下标分别为0和1
- 不指定第一维长度的初始化
int a[][3]={{1,2,3},{4,5},{6},{0}};
int a[][4]={1,2,3,4,5,6,7,8}; (根据列数和元素总数可计算行数)
int a[][4]={ {0,0,3},{ },{0,10}};
4 向函数传递数组
4.1 一维数组传递
- 数组名代表数组的首地址。
- 数组名也可以作实参和形参,
传递的是数组的起始地址
。 - 调用函数时,
实参必须是数组名
- 例:编写函数实现一维数组的输入输出。
- 输入函数的原型为:
void input(int a[], int n);
其中第一个参数为int数组,第二个参数为数组的大小。
调用:input(a,size); - 输出函数的原型为:
void print(int [], int);
其中第一个参数为int数组,第二个参数为数组的大小。注意在函数的原型说明中,可以去掉形参名。
调用:print(a,size);
- tips
- 当函数原型是这两种写法时
void func(int p[], int n)
void func(int p[10], int n)
- 上面的两个例子,好像定义了一个数组,甚至元素个数都加进去了,实际上这两种形式的数组定义都是假象。
两者都不会创建一个数组出来,最终还是会转换为指针*p
。 int p[10]
这种形式只能说明函数期望用户传递的数组有 10个元素,并不意味着数组只能有 10 个元素
,真正传递的数组可以有少于或多于10 个的元素。- 参数的传递本质上是一次赋值的过程,赋值就是对内存进行拷贝。而数组中数据的数量没有限制,可能非常多,对它们进行内存拷贝有可能是一个漫长的过程,会严重拖慢程序的效率,为了规避上述情况,C语言没有从语法上支持数据集合的直接赋值。
4.2 二维数组传递
- 在函数定义时,
形式参数
可以明确指定二维数组的行数和列数,也可以不指定行数,但必须指定二维数组的列数
!
int MA(int a[3][10]);
int MA(int a[][10]);
4.3 将数组名作为参数传递时
- 在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么,数据的传送是如何实现的呢?在我们曾介绍过,数组名就是数组的首地址。因此
在数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名
。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组
,共同拥有一段内存空间
。因此当形参数组发生变化时,实参数组也随之变化
。 - 声明形参数组并不意味着真正建立一个包含若干元素的数组,
在调用函数时也不它分配存储单元
,只是用array[]这样的形式表示array是一维数组名,以接收实参传来的地址。因此array[]中方括号内的数值并无实际作用
,编译系统对一维数组方括号内的内容不予处理。形参一维数组的声明中可以写元素个数,也可以不写
。 多维数组也可以作为函数的参数
。在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。因此,以下写法都是合法的:int MA(int a[3][10]);或int MA(int a[][10]);
- 看了这篇数组名作为参数传递给函数就可以解释第五点
- 在函数形参表中,允许不给出形参数组的长度,或用一个变量来表示数组元素的个数。例如,可以写为:
void nzp(int a[])
或写为
void nzp( int a[], int n )
其中形参数组a没有给出长度,而由n值动态地表示数组的长度。n的值由主调函数的实参进行传送。
数组作为函数参数时,最好将数组大小也作为一个函数参数