深入浅出C语言:(四)函数

目录

一、函数调用详解(从中发现程序运行的秘密)

二、函数声明以及函数原型

三、全局变量和局部变量

四、C 语言变量的作用域

五、C 语言块级变量(在代码块内部定义的变量)

六、再谈作用域

七、C 语言递归函数(递归调用)

八、递归的条件


一、函数调用详解(从中发现程序运行的秘密)

在 C 语言中,函数调用的方式有多种,例如:

1. 函数作为表达式中的一项出现在表达式中
2. z = max(x, y);
3. m = n + max(x, y);

4. 函数作为一个单独的语句
5. printf("%d", a);
6. scanf("%d", &b);

7. 函数作为调用另一个函数时的实参
8. printf( "%d", max(x, y) );
9. total( max(x, y), min(m, n) );

二、函数声明以及函数原型

       C 语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错。但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明。
       所谓声明(Declaration) ,就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。
       函数声明的格式非常简单,相当于去掉函数定义中的函数体,并在最后加上分号;如下所示:

dataType functionName( dataType1 param1, dataType2 param2 ... );

       也可以不写形参,只写数据类型

dataType functionName( dataType1, dataType2 ... );

       函数声明给出了函数名、返回值类型、参数列表(重点是参数类型)等与该函数有关的信息,称为函数原型(FunctionPrototype) 。函数原型的作用是告诉编译器与该函数有关的信息,让编译器知道函数的存在,以及存在的形式,即使函数暂时没有定义,编译器也知道如何使用它。
       有了函数声明,函数定义就可以出现在任何地方了,甚至是其他文件、静态链接库、动态链接库等。

//函数声明
int sum(int m, int n); //也可以写作int sum(int, int);

       对于多个文件的程序,通常是将函数定义放到源文件(.c 文件)中,将函数的声明放到头文件(.h 文件)中,使用函数时引入对应的头文件就可以,编译器会在链接阶段找到函数体。

函数声明的例子:

三、全局变量和局部变量

1、局部变量:
       定义在函数内部的变量称为局部变量(Local Variable) ,它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。 例如:

int love(int a)
{
   int b,c;       a,b,c仅在函数love()内有效
   return a+b+c;
}


int main()
{
   int m,n;       m,n仅在函数main()内有效
   return 0;
}

几点说明:

  1. main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时, main 函数中也不能使用其它函数中定义的变量。 main 函数也是一个函数,与其它函数地位平等。
  2. 形参变量、在函数体内定义的变量都是局部变量。 实参给形参传值的过程也就是给局部变量赋值的过程。
  3. 可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。
  4. 在语句块中也可定义变量,它的作用域只限于当前语句块
     

2、全局变量:
        在所有函数外部定义的变量称为全局变量(Global Variable) ,它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。 例如:

int a, b;     全局变量

void func1()
{
//TODO:
}

float x,y;    全局变量
int func2()
{
//TODO:
}

int main()
{
//TODO:
return 0;
}

a、 b、 x、 y 都是在函数外部定义的全局变量。

四、C 语言变量的作用域

       所谓作用域(Scope) ,就是变量的有效范围,就是变量可以在哪个范围以内使用。有些变量可以在所有代码文件中使用,有些变量只能在当前的文件中使用,有些变量只能在函数内部使用,有些变量只能在 for 循环内部使用。
       变量的作用域由变量的定义位置决定,在不同位置定义的变量,它的作用域是不一样的。 本节我们只讲解两种变量,一种是只能在函数内部使用的变量,另一种是可以在所有代码文件中使用的变量。

1、在函数内部定义的变量(局部变量)

       在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了,我们将这样的变量称为局部变量(Local Variable) 。函数的形参也是局部变量,也只能在函数内部使用。请看下面的例子:
2、在所有函数外部定义的变量(全局变量)
       在一个函数内部修改全局变量的值会影响其它函数,全局变量的值在函数内部被修改后并不会自动恢复,它会一直保留该值,直到下次被修改。
       全局变量也是变量,变量只能保存一份数据,一旦数据被修改了,原来的数据就被冲刷掉了,再也无法恢复了,所以不管是全局变量还是局部变量,一旦它的值被修改,这种影响都会一直持续下去,直到再次被修改。

3、关于变量的命名

  1. 不同函数内部的同名变量是两个完全独立的变量,它们之间没有任何关联,也不会相互影响。
  2. 函数内部的局部变量和函数外部的全局变量同名时,在当前函数这个局部作用域中,全局变量会被“屏蔽”,不再起作用。也就是说,在函数内部使用的是局部变量,而不是全局变量。变量的使用遵循就近原则,如果在当前的局部作用域中找到了同名变量,就不会再去更大的全局作用域中查找。另外,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。

五、C 语言块级变量(在代码块内部定义的变量)

C 语言还允许出现单独的代码块,它也是一个作用域。

#include <stdio.h>
int main()
{
   int n = 22; //编号①
   由{ }包围的代码块
{
   int n = 40; //编号②
   printf("block n: %d\n", n);
}
   printf("main n: %d\n", n);
   return 0;
}

运行结果:
block n: 40
main  n: 22

六、再谈作用域

       每个 C 语言程序都包含了多个作用域,不同的作用域中可以出现同名的变量, C 语言会按照从小到大的顺序、一层一层地去父级作用域中查找变量,如果在最顶层的全局作用域中还未找到这个变量,那么就会报错。

七、C 语言递归函数(递归调用)

       一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层,当最内层的函数执行完毕后,再一层一层地由里到外退出。

求n的阶乘
long factorial(int n) 
{
if (n == 0 || n == 1) 
{
return 1;
}
else 
{
return factorial(n - 1) * n;  递归调用
}
}

八、递归的条件

       每一个递归函数都应该只进行有限次的递归调用,否则它就会进入死胡同,永远也不能退出了,这样的程序是没有意义的。
       要想让递归函数逐层进入再逐层退出,需要解决两个方面的问题:

  1. 存在限制条件,当符合这个条件时递归便不再继续。对于 factorial(),当形参 n 等于 0 或 1 时,递归就结束了。
  2. 每次递归调用之后越来越接近这个限制条件。对于 factorial(),每次递归调用的实参为 n - 1,这会使得形参 n的值逐渐减小,越来越趋近于 1 或 0。
     

       标准 C 语言(ANSI C)共定义了 15 个头文件,称为“C 标准库”,所有的编译器都必须支持,如何正确并熟练的使用这些标准库,可以反映出一个程序员的水平。

  • 合格程序员: <stdio.h>、 <ctype.h>、 <stdlib.h>、 <string.h>
  • 熟练程序员: <assert.h>、 <limits.h>、 <stddef.h>、 <time.h>
  • 优秀程序员: <float.h>、 <math.h>、 <error.h>、 <locale.h>、 <setjmp.h>、 <signal.h>、 <stdarg.h>
     

 

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值