[C] 7 函数

版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83926187

  • 一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。

  • 实参与形参间的数据传递,常称为“虚实结合”

  • 被调用的函数必须是已经定义的函数

  • 声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法(在调用之前申请即可)

  • 编译系统只关心和检查参数个数和参数类型,而不检查参数名

float add(float a,float b)
float add(float , float) //合法

递归

递归:回溯到特殊的情况,然后递推往上计算

问题集

  1. n!
  2. 汉诺塔

数组作为函数参数

一维数组

  1. 数组元素作实参时,向形参变量传递的是数组元素的
  2. 数组名作函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址
float average(float array[10]); 
	//指定大小是不起作用的,编译系统不检查形参数组大小,只是将首元素的地址传给形参数组名
float average(float array[]); //合法
float average(float *array); //本质

多维数组

// 不合法
int array[][]; //不合法
	//二维数组是由若干个一维数组组成的
	//在内存中,数组是按行存放的
	//因此,在定义二维数组时,必须指定列数(即一行中包含几个元素)
	//由于形参数组与实参数组类型相同,所以它们是由具有相同长度的一维数组所组成的
int array[3][]; //不合法
	//不能只指定第一维(行数)而省略第二维(列数)
// 合法
int array[3][10];
int array[][10]; //省略第一维的大小
int array[2][10];
	//三者效果相同,编译器不检查第一维的大小

局部变量和全局变量

从变量的作用域(即从空间)的角度来观察,变量可以分为全局变量和局部变量

局部变量

定义3种情况:

  1. 在函数的开头定义;
  2. 在函数内的复合语句内定义;
  3. 在函数的为外部定义

作用域:

  • 在函数内部定义的变量只在本函数范围内有效–>只有在本函数内才能引用它们,在此函数以外是不能使用这些变量的

  • 在复合语句内定义的变量只在本复合语句范围内有效–>只在本复合语句内才能引用它们

全局变量

在函数之外定义的变量称为外部变量,外部变量是全局变量(全称变量)

全局变量可以为本文件中其他函数所共用。
它的有效范围为从定义变量的位置开始到本源文件结束

习惯:全局变量第一个字母大写

变量的存储方式和生存期

动态存储方式与静态存储方式

从变量值**存在的时间(即生存期)**来观察
有的变量在程序运行的整个过程都是存在的,而有的变量则是在调用其所在的函数时才临时分配存储单元,而在函数调用结束后该存储单元就马上释放,变量就不在了

  1. 静态存储方式
    在程序运行期间由系统分配固定的存储空间的方式

  2. 动态存储方式
    在程序运行期间根据需要进行动态的分配存储空间的方式

用户区:内存中的供用户使用的存储空间的情况

  1. 程序区
  2. 静态存储区:全局变量
  3. 动态存储区
    • 函数形式参数:在调用函数时给形参分配存储空间
    • 函数中定义的没有用关键字static声明的变量,即自动变量
    • 函数调用时的现场保护和返回地址等

局部变量的存储类别

每个变量和函数都有两个属性:

  1. 数据类型:浮点型、整型
  2. 数据的存储类别:在内存中的存储方式(静态存储和动态存储)

自动变量auto

系统给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间
属于动态存储类别

变量定义默认为auto

int a=0; 即 auto int a=0;
auto int a; //没有赋初值,没有默认值,值是一个不确定的值

自动变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次函数重新给一次初值,相当于执行一次赋值语句

静态局部变量static

在函数调用结束后不消失而继续保留原值

静态存储区内分配存储单元
在编译时执行定义语句,并赋初值,默认值为0,’\0’,以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值

寄存器变量register

变量工作原理:一般情况下,变量(包括静态存储方式和动态存储方式)的值都是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。

为提高执行效率,允许将局部变量的值放在CPU中的寄存器
需要用时直接从寄存器取出参加运算,不必再到内存中去存取

register int f;

全局变量的存储类别

全局变量都是存放在静态存储区中的

在编译时遇到extern时,先在本文件中找外部变量的定义

  • 找到,就在本文件中扩展作用域
  • 找不到,就在连接时从其他文件中找外部变量的定义
    • 从其他文件中找到,就将作用域扩展到本文件
    • 找不到,出错处理

在一个文件内扩展外部变量的作用域extern

如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件结束,在定义点之前的函数不能引用该外部变量

main() {
	extern int A,B,C; //main之前没有定义A,B,C。如果没有extern则不能使用
		//这里使用extern把外部变量A,B,C的作用域扩展到从此开始
	... //可以使用A,B,C
}

int A,B,C;

将外部变量的作用扩展到其他文件extern

// //文件file1.c
int A; //定义外部变量
int main() {
	...//使用A
}

// //文件file2.c
extern A; //把在file1文件中已定义的外部变量作用域扩展到本文件
int power(int n) {
	... //使用A
}

将外部变量的作用域限制在本文件中

只限于被本文件引用,而不能被其他文件引用。加static,称为静态外部变量

// //file1.c
static int a; //只能用于本文件
main() {}

// //file2.c
extern A;
void fun() {
	A = A*2; //出错
}

static

  1. 对局部变量用static声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终存在
  2. 对全局变量用static声明,则该变量的作用域只限于本文件模块(即被声明的文件中)

猜你喜欢

转载自blog.csdn.net/summer_dew/article/details/83926187