【C语言】MOOC翁恺老师-入门-函数-5
函数
-
问题:写了函数有什么好处?有没有什么亲身感受能体会到函数的好、函数的美?
答:1.当遇到重复的代码的时候,就可以通过使用函数来简化代码,而且当其他源程序要用到这个代码块的功能的时候,直接复制函数过去就可以了。 2.亲身体会,输出题目所需要的输入的时候,可以把判断是不是素数的代码提出来定义成函数,简化效果很明显,也更易于理解主函数了。 3.当要维护程序时,工作量能大大减小
-
函数定义:函数是一块代码,接受0个或多个参数,做一件事情,并返回0个或一个值。
-
函数返回值:最好也遵循着
单一出口
原则进行编码! -
函数的先后关系:C的编译器是自上而下顺序分析代码。因此被调用的函数要写在main函数的上方,让编译器先知道被调用的函数什么情况。当在main函数中执行到相关调用函数的时候,编译器就知道(我刚才遇到过,然后回去上面调用)。
-
函数原型:
-
背景:在C99之前,如果不按现有规则去编写函数顺序,比如说main函数在最上面,而main函数里面要调用的函数在下面。那么main函数会在执行到相关调用函数的时候自己猜想着定义一个函数。可是这样的话执行到下面遇到真正由程序员定义的函数就会引发冲突。所以为了解决这一情况,在C99标准之后,我们严格遵守函数的先后关系原则便可以避免这样的冲突。或者,有些人出于自己的编码习惯,一定要把main函数放在最上面,自己定义的函数放在下面,那么可以使用到函数原型来避免这样的冲突发生。
-
定义:函数头以分号为结尾,放在main函数的最上面。
double max(double a, double b); // 函数原型声明 int main() { max(10.0, 20.0); // 调用函数 .... } double max(double a, double b) // 函数定义 { .... }
-
-
函数中形参和实参类型不匹配问题:
- 调用函数时给的值与参数的类型不匹配是C语言传统上最大的漏洞
- 编译器总是悄悄地把你的类型转换好,但是这很可能不是你所期望的
- 后续的语言中,C++/Java在这方面很严格
-
函数传值:
- 每个函数都有自己的变量空间,参数也位于这个独立的空间中,和其它函数没有关系。每个参数都有自己的生命周期。
- 函数的调用在传递的时候仅仅只是
传值
,而不是把变量传进去! - 传统的形参和实参概念容易让人误会,现在我们认为,函数调用是参数和值的关系问题
-
本地变量:
-
函数的每次运行,就产生了一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量。
-
定义在函数内部的变量就是本地变量,参数也是本地变量。
-
对于本地变量,生存期和作用域都是在大括号内的块
补充:
- 生存期:什么时候这个变量开始出现,到什么时候消亡
- 作用域:在什么范围内这个变量可以起到作用
-
块外面定义的变量在里面依然有效
int main() { int a = 6; if(1){ printf("%d", a); // 输出6 } }
-
块里面定义了和外面同名的变量则掩盖了外面的,但同样出了块外就消亡了
int main() { int a = 6; if(1){ a = 0; // 掩盖了外面-块内同名遵循就近原则 printf("%d", a); // 输出0 } }
-
本地变量不会被默认初始化,C语言的类型都这样,所以要特别注意给初始化!参数除外,因为调用的时候已经传值初始化了。
-
-
其它细节:
-
如果函数原型声明的时候,没有参数那就写
void
void max(void); // 参数里面没有参数,记得写上void,至少C语言要这样
-
调用函数时的逗号和逗号运算符怎么区分?
f(a,b) // 逗号,调用函数的逗号没有作用,只是区分两个数字 f((a,b), c) // 逗号运算符( , )是C语言运算符中优先级最低的一种运算符。 a = 12+(s+2,d+4); // 逗号运算符,括号内算完会取后一个的数,即d+4的值
-
C语言不允许函数的嵌套定义,而Python中的高级函数可以
-