数组
定义数组
-
<数组类型>
变量名称 [元素数量] -
int grades[100];
-
double weight[20];
-
元素数量必须是整数(在C99编译器中可以用动态变量)
-
一旦创建,就不能改变大小
-
数组中的元素在内存中是连续依次排列的
数组的单元
-
数组的每个单元就是数组类型的一个变量
-
使用数组时放在[]中的数字叫做下标或索引,下标从0开始计数,直到下标为元素个数-1
有效的下标范围
-
编译器和运行环境都不会检查数组下表是否越界
-
越界的数组访问可能会造成问题,导致程序崩溃,也可能运气好不会造成严重结果
-
可以让用户先输入将要输入的个数,赋给变量,让这个变量作为数组大小(仅限C99编译器)
函数
函数定义
- <函数类型> 函数名(参数值){
函数体
}
-
调用时即使没有参数也需要()
-
如果有参数,则需要给出正确的数量和顺序
从函数中返回值
-
return
可以停止函数的执行,并送回一个结果 -
一个函数中可以出现多个
return
(不是单一出口,修改起来很麻烦,不推荐使用) -
void
类型表示没有返回值的函数- 不能使用带值的
return
- 可以没有
return
- 不能使用带值的
调用函数
-
在调用函数前要在前面加上函数原型声明(以分号结尾),要与函数头一致
-
传递给函数的值可以是表达式的结果,这包括:
- 字面量
c=max(10,12);
- 变量
c=max(a,b);
- 函数的返回值
c=max(c,23);
c=max(max(15,62),a);
- 计算的结果
c=max(10+36,b);
- 字面量
-
当调用函数时给的值与参数的类型不匹配时,C语言传统编译器会自动把类型转换,可能会导致出漏洞
-
函数参数表中的参数,叫做“形式参数”,调用函数时给的值,叫做“实际参数”
-
调用函数时传入的实参只是一个值,并不是把变量传进去计算,函数中值的计算跟实参没有一点关系
本地变量的规则
-
块,即某个大括号划分的区域
-
本地变量是定义在块内的
-
它可以定义在函数的块内,也可以定义在语句的块内
-
甚至可以随便拉一对大括号来定义变量
-
程序运行进入这个块之前,其中的变量不存在,离开这个块,其中的变量就消失了
-
块外面定义的变量在里面仍然有效
-
块里面定义了和外面同名的变量,则会覆盖外面的值
-
不能在一个块内定义同名的变量
-
本地变量不会被默认初始化
-
参数在进入函数的时候就被初始化了
本地变量
-
函数的每次运行,都会产生一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量
-
定义在函数内部的变量就是本地变量
-
参数也是本地变量
其他事项
-
当没有参数时
- 是写
void f(void);
,而不是void f();
,这个表示f函数的参数表未知,并不表示没有参数
- 是写
-
C语言不允许函数嵌套定义
数组运算
数组的集成初始化
-
int a[] = {2,4,6,8,10,12,14,16,18,22,26}
-
定位(仅限C99):
int a[10] = {
[0]=2, [2]=3,6,
};
-
其他没有给值的自动补零
-
适用于初始数据稀疏的数组,很多都是0
数组的大小
-
sizeof
给出整个数组所占据的内容的大小,单位是字节 -
sizeof(a) / sizeof(a[0])
-
sizeof(a[0])
给出数组中单个元素的大小,于是相除就得到了数组的单元个数
数组的赋值
-
数组变量本身不能被赋值
-
要把一个数组的所有元素交给另一个数组,必须采用遍历一个一个元素替换
数组的遍历
-
通常都是使用for循环,让循环变量i从0到<数组长度,这样循环体内最大的正好是数组最大的有效下标
-
常见错误是:
- 循环结束条件是<=数组长度
- 离开循环后,继续用i的值来做数组元素的下标
注意
-
数组作为函数的参数时:
-
无法在函数中给出数组的大小
-
不能再利用sizeof来计算数组的元素个数
-
-
这是因为在函数调用时,数组名会被解释为数组的第一个元素的地址。因此,函数只能获取到数组的起始地址,并不知道数组的长度。
-
所以数组作为函数参数时,往往需要再用另一个参数来传入数组的大小
二维数组
-
例:
int a[3][5]; //[行数][列数]
-
通常理解为a是一个3行5列的矩阵
-
遍历:
for(i=0;i<3;i++){
for(j=0;j<5;j+){
a[i][j] = i*j;
}
}
- 初始化:
int a[][5]={
{0,1,2,3,4},
{2,3,4,5,6},
};
-
列数是必须给出的,行数可以由编译器来数
-
每行一个{},逗号分隔;如果省略,表示补零