初识C语言之函数封装篇——带你嗅探万花从中的清香(上)

举报
王小王-123 发表于 2021/07/01 00:37:20 2021/07/01
【摘要】 函 数 概 述 构成C程序的基本单元是函数。函数中包含程序的可执行代码。 每个C程序的入口和出口都位于main函数之中。编写程序时,并不是将所有的内容都放在主函数main中。为了方便规划、组织、编写和调试,一般的做法是将一个程序划分成若干个程序模块,每一个程序模块都完成一部分功能。这样,不同的程序模块可以由不同的人来完成,从而可以提高软件开发的效率。 也就是说,主函数可...

函 数 概 述

构成C程序的基本单元是函数。函数中包含程序的可执行代码。

每个C程序的入口和出口都位于main函数之中。编写程序时,并不是将所有的内容都放在主函数main中。为了方便规划、组织、编写和调试,一般的做法是将一个程序划分成若干个程序模块,每一个程序模块都完成一部分功能。这样,不同的程序模块可以由不同的人来完成,从而可以提高软件开发的效率。

也就是说,主函数可以调用其他的函数,其他函数也可以相互调用。在main函数中调用其他的函数,这些函数执行完毕之后又返回到main函数中。通常把这些被调用的函数称为下层函数。函数调用发生时,立即执行被调用的函数,而调用者则进入等待的状态,直到被调用函数执行完毕。函数可以有参数和返回值。

某程序的函数调用示意图

【实例9.1】 在主函数中调用其他函数。


  
  1. #include<stdio.h>
  2. void Move(); /*声明搬运函数*/
  3. void Build(); /*声明建造函数*/
  4. void Paint(); /*声明粉刷函数*/
  5. int main()
  6. {
  7. Move(); /*执行搬运函数*/
  8. Build(); /*执行建造函数*/
  9. Paint(); /*执行粉刷函数*/
  10. return 0; /*程序结束*/
  11. }
  12. /*执行搬运功能 */
  13. void Move()
  14. {
  15. printf("This Function can move material\n");
  16. }
  17. /*执行建造功能 */
  18. void Build()
  19. {
  20. printf("This Function can build a building\n");
  21. }
  22. /* 执行粉刷功能 */
  23. void Paint()
  24. {
  25. printf("This Function can paint cloth\n");
  26. }

函数的定义

在程序中编写函数时,函数的定义是让编译器知道函数的功能。定义的函数包括函数头和函数体两部分。

函数头

分为3个部分:

返回值类型。返回值可以是某个C数据类型。

函数名。函数名也就是函数的标识符,函数名在程序中必须是唯一的。因为是标识符,所以函数名也要遵守标识符命名规则。
参数表。参数表可以没有变量也可以有多个变量,在进行函数调用时,实际参数将被复制到这些变量中。

函数体

函数体包括局部变量的声明和函数的可执行代码。

函数定义的形式

C语言的库函数在编写程序时是可以直接调用的,例如printf输出函数。而自定义函数则必须由用户对其进行定义,在其函数的定义中完成函数特定的功能,这样才能被其他函数调用。

一个函数的定义分为两个部分,函数头和函数体。

函数定义的语法格式如下:  定义一个函数的代码如下:


  
  1. 返回值类型 函数名(参数列表)
  2. {
  3. 函数体(函数实现特定功能的过程);
  4. }

  
  1. int AddTwoNumber(int iNum1,int iNum2) /*函数头部分*/
  2. {
  3. /*函数体部分,实现函数的功能*/
  4. int result; /*定义整型变量*/
  5. result = iNum1+iNum2; /*进行加法操作*/
  6. return result; /*返回操作结果,结束*/
  7. }

通过代码分析一下定义函数的过程:

函数头

函数头用来表示标志一个函数代码的开始,这是一个函数的入口处。函数头分成3个部分:

返回值类型。
函数名

参数列表

函数体

函数体位于函数头的下方位置,由一对大括号括起来,大括号决定了函数体的范围。函数要实现的特定功能,都是在函数体这个部分通过代码语句完成的。最后通过return语句返回实现的结果。在上面的代码中,AddTwoNumber函数的功能是实现两个整数加法,因此定义一个整数用来保存加法的计算结果,之后利用传递进来的参数进行加法操作,并将结果保存在result变量中,最后函数要将所得到的结果进行返回。通过这些语句的操作,实现了函数的特定功能。

函数分类

现在已经了解到定义一个函数应该使用怎样的语法格式,在定义函数时会有如下几种特殊的情况:

无参函数

无参函数也就是没有参数的函数。无参函数语法形式如下:


  
  1. 返回值类型 函数名()
  2. {
  3. 函数体
  4. }

空函数

顾名思义,空函数就是没有任何内容的函数,也没有什么实际作用。空函数既然没有什么实际功能那么为什么要存在呢?原因是空函数所处的位置是要放一个函数的,只是这个函数现在还未编好,用这个空函数先占一个位置,以后用一个编好的函数来取代它。

空函数的形式如下:


  
  1. 类型说明符 函数名()
  2. {
  3. }

定义与声明

在程序中编写函数时,要先对函数进行声明,再对函数进行定义。函数的声明是让编译器知道函数的名称、参数、返回值类型等信息。函数的定义是让编译器知道函数的功能。

函数的声明的格式由函数返回值类型、函数名、参数列表和分号4部分组成。

返回值类型  函数名(参数列表);

此处要注意的是在声明的最后要有分号“;”作为语句的结尾。例如,声明一个函数的代码如下:

int ShowNumber(int iNumber);

【实例9.2】 函数的定义与声明。


  
  1. #include<stdio.h>
  2. /*函数的声明*/
  3. void ShowNumber(int iNumber);
  4. int main()
  5. {
  6. int iShowNumber; /*定义整型变量*/
  7. printf("What Number do you wanna show?\n");/*输出提示信息*/
  8. scanf("%d",&iShowNumber); /*输入整数*/
  9. ShowNumber(iShowNumber); /*调用函数*/
  10. return 0; /*程序结束*/
  11. }
  12. /*函数的定义*/
  13. void ShowNumber(int iNumber)
  14. {
  15. printf("You wanna to show the Number is:%d\n",iNumber);/*输出整数*/
  16. }

返回语句

从函数返回

【实例9.3】 从函数返回。


  
  1. int Function() /*定义函数*/
  2. {
  3. printf("this step is in the function\n");/*输出提示信息*/
  4. /*函数结束*/
  5. }

  
  1. #include<stdio.h>
  2. int Function(); /*声明函数*/
  3. int main()
  4. {
  5. printf("this step is before the Function\n"); /*输出提示信息*/
  6. Function(); /*调用函数*/
  7. printf("this step is end of the Function\n"); /*输出提示信息*/
  8. return 0;
  9. }

返回值

通常调用者希望能调用其他函数得到一个确定的值,这就是函数的返回值。例如下面的代码:


  
  1. int Minus(int iNumber1,int iNumber2)
  2. {
  3. int iResult; /*定义一个整型变量用来存储返回的结果*/
  4. iResult=iNumber1-iNumber2; /*进行减法计算,得到计算结果*/
  5. return result; /*return语句返回计算结果*/
  6. }
  7. int main()
  8. {
  9. int iResult; /*定义一个整型变量*/
  10. iResult=Minus(9,4);/*进行9-4的减法计算,并将结果赋值给变量iResult*/
  11. return 0; /*程序结束*/
  12. }

上面的代码中,可以看到首先定义了一个进行减法操作的函数Minus,在主函数main中通过调用Minus将计算的减法结果赋值给在main中定义的变量iResult。

【实例9.4】 返回值类型与return值类型


  
  1. #include<stdio.h>
  2. char ShowChar(); /*函数的声明*/
  3. int main()
  4. {
  5. char cResult;
  6. cResult=ShowChar(); /*进行9-4的减法计算,并将结果赋值给变量iResult*/
  7. printf("%c\n",cResult); /*将返回的结果进行输出*/
  8. return 0; /*程序结束*/
  9. }
  10. char ShowChar()
  11. {
  12. int iNumber; /*定义整型变量*/
  13. printf("please input a number:\n"); /*输出提示信息*/
  14. scanf("%d",&iNumber);/*输入一个整型变量*/
  15. return iNumber; /*返回的是整型*/
  16. }

函数参数

形式参数与实际参数

在使用函数时,经常会用到形式参数和实际参数。两者都叫做参数,那么二者有什么关系?二者之间的区别是什么?两种参数各自又起到什么作用?接下来通过形式参数与实际参数的名称和作用来进行理解,再通过一个比喻和实例进行深入理解。

通过名称理解

形式参数,按照名称进行理解就是形式上存在的参数。

实际参数,按照名称进行理解就是实际存在的参数。

通过作用理解

形式参数:在定义函数时,函数名后面括号中的变量名称为“形式参数”。在函数调用之前,传递给函数的值将被复制到这些形式参数中。

实际参数:在调用一个函数时,也就是真正使用一个函数时,函数名后面括号中的参数为“实际参数”。函数的调用者提供给函数的参数叫实际参数。实际参数是表达式计算的结果,并且被复制给函数的形式参数。

通过一个比喻来理解形式参数和实际参数

母亲拿来了一袋牛奶,将牛奶倒入一个空奶瓶中,然后喂宝宝喝牛奶。函数的作用就相当于宝宝用奶瓶喝牛奶这个动作,实参相当于母亲拿来的一袋牛奶,而空的奶瓶就相当于形参。牛奶放入奶瓶这个动作相当于将实参传递给形参,使用灌好牛奶的奶瓶就相当于函数使用参数进行操作的过程。

【实例9.5】 形式参数与实际参数的比喻实现。


  
  1. #include<stdio.h>
  2. void DrinkMilk(char* cBottle); /*声明函数*/
  3. int main()
  4. {
  5. char cPoke[]=""; /*定义字符数组变量*/
  6. printf("Mother wanna give the baby:"); /*输出信息提示*/
  7. scanf("%s",&cPoke); /*输入字符串*/
  8. DrinkMilk(cPoke); /*将实际参数传递给形式参数*/
  9. return 0; /*程序结束*/
  10. }
  11. /*喝牛奶的动作*/
  12. void DrinkMilk(char* cBottle) /*cBottle为形式参数*/
  13. {
  14. printf("The Baby drink the %s\n",cBottle); /*输出提示,进行喝牛奶动作*/
  15. }

数组作函数参数

本节将讨论数组作为实参传递给函数的这种特殊情况。将数组作为函数参数进行传递,不同于标准的赋值调用的参数传递方法。

当数组作为函数的实参时,只传递数组的地址,而不是将整个数组赋值到函数中。当用数组名作为实参调用函数时,指向该数组的第一个元素的指针就被传递到函数中。

声明函数参数时必须具有相同的类型,根据这一点,下面将对使用数组作为函数参数的各种情况进行详细的讲解。

使用数组元素作为函数参数

由于实参可以是表达式形式,数组元素可以是表达式的组成部分,因此数组元素可以作为函数的实参,与用变量作为函数实参一样,是单向传递。

【实例9.6】 数组元素作为函数参数。


  
  1. #include<stdio.h>
  2. void ShowMember(int iMember); /*声明函数*/
  3. int main()
  4. {
  5. int iCount[10]; /*定义一个整型的数组*/
  6. int i; /*定义整型变量,用于循环*/
  7. for(i=0;i<10;i++) /*进行赋值循环*/
  8. {
  9. iCount[i]=i; /*为数组中的元素进行赋值操作*/
  10. }
  11. for(i=0;i<10;i++) /*循环操作*/
  12. {
  13. ShowMember(iCount[i]);/*执行输出函数操作*/
  14. }
  15. return 0;
  16. }
  17. void ShowMember(int iMember) /*函数定义*/
  18. {
  19. printf("Show the member is%d\n",iMember);/*输出数据*/
  20. }

数组名作为函数参数

可以用数组名作为函数参数,此时实参与形参都使用数组名。

【实例9.7】 数组名作为函数参数。


  
  1. #include<stdio.h>
  2. void Evaluate(int iArrayName[10]);/*声明赋值函数*/
  3. void Display(int iArrayName[10]); /*声明显示函数*/
  4. int main()
  5. {
  6. int iArray[10]; /*定义一个具有10个元素的整型数组*/
  7. Evaluate(iArray[10]);/*调用函数进行赋值操作,将数组名作为参数*/
  8. Display(iArray[10]);/*调用函数进行赋值操作,将数组名作为参数*/
  9. return 0;
  10. }
  11. void Display(int iArrayName[10])
  12. {
  13. int i; /*定义整型变量*/
  14. for(i=0;i<10;i++) /*执行循环的语句*/
  15. { /*在循环语句中执行输出操作*/
  16. printf("the member number is %d\n",iArrayName[i]);
  17. }
  18. }
  19. /* 进行数组元素的赋值 */
  20. void Evaluate(int iArrayName[10])
  21. {
  22. int i; /*定义整型变量*/
  23. for(i=0;i<10;i++) *执行循环语句*/
  24. { /*在循环语句中执行赋值操作*/
  25. iArrayName[i]=i;
  26. }
  27. }

可变长度数组作为函数参数

可以用数组名作为函数参数,此时实参与形参都使用数组名。

【实例9.8】 可变长度数组作为函数参数。


  
  1. #include<stdio.h>
  2. void Evaluate(int iArrayName[]); /*声明函数,参数为可变长度数组*/
  3. void Display(int iArrayName[]); /*声明函数,参数为可变长度数组*/
  4. int main()
  5. {
  6. int iArray[10];/*定义一个具有10个元素的整型数组*/
  7. Evaluate(iArray[10]);/*调用函数进行赋值操作,将数组名作为参数*/
  8. Display(iArray[10]);/*调用函数进行赋值操作,将数组名作为参数*/
  9. return 0;
  10. }
  11. void Display(int iArrayName[]) /*定义函数,参数为可变长度数组*/
  12. {
  13. int i; /*定义整型变量*/
  14. for(i=0;i<10;i++) /*执行循环的语句*/
  15. { /*在循环语句中执行输出操作*/
  16. printf("the member number is %d\n",iArrayName[i]);
  17. }
  18. }
  19. /*进行数组元素的赋值*/
  20. void Evaluate(int iArrayName[]) /*定义函数,参数为可变长度数组*/
  21. {
  22. int i; /*定义整型变量*/
  23. for(i=0;i<10;i++) /*执行循环语句*/
  24. { /*在循环语句中执行赋值操作*/
  25. iArrayName[i]=i;
  26. }
  27. }

使用指针作为函数参数

最后一种方式是将函数参数声明为一个指针。

【实例9.9】 指针作为函数参数


  
  1. #include<stdio.h>
  2. void Evaluate(int* pPoint);/*声明函数,参数为可变长度数组*/
  3. void Display(int* pPoint);/*声明函数,参数为可变长度数组*/
  4. int main()
  5. {
  6. int iArray[10]; /*定义一个具有10个元素的整型数组*/
  7. Evaluate(iArray); /*调用函数进行赋值操作,将数组名作为参数*/
  8. Display(iArray); /*调用函数进行赋值操作,将数组名作为参数*/
  9. return 0;
  10. }
  11. void Display(int* pPoint)/*定义函数,参数为可变长度数组*/
  12. {
  13. int i; /*定义整型变量*/
  14. for(i=0;i<10;i++) /*执行循环的语句*/
  15. { /*在循环语句中执行输出操作*/
  16. printf("the member number is %d\n",pPoint[i]);
  17. }}
  18. void Evaluate(int* pPoint) /*定义函数,参数为可变长度数组*/
  19. {
  20. int i; /*定义整型变量*/
  21. for(i=0;i<10;i++) /*执行循环语句*/
  22. { /*在循环语句中执行赋值操作*/
  23. pPoint[i]=i;
  24. }}

main的参数

在前面介绍函数定义的内容中,曾在讲解函数体时提到过主函数main的有关内容,下面在此基础上对main函数的参数进行介绍。

在运行程序时,有时需要将必要的参数传递给主函数。主函数main的形式参数如下:

main (int argc, char* argv[] )   

两个特殊的内部形参argc和argv是用来接收命令行实参的,这是只有主函数main才能具有的参数。

argc参数

argc参数保存命令行的参数个数,是整型变量。这个参数的值至少是1,因为至少程序名就是第一个实参。

argv参数

argv参数是一个指向字符指针数组的指针,这个数组里的每一个元素都指向命令行实参。所有命令行实参都是字符串,任何数字都必须由程序转变成为适当的格式。

【实例9.10】 main的参数使用。


  
  1. #include<stdio.h>
  2. int main(int argc,char* argv[])
  3. {
  4. printf("%s\n",argv[0]);/*输出程序的位置*/
  5. return 0; /*程序结束*/
  6. }

函数的调用

函数调用方式

一种工具不只有一种使用方式,函数的调用也是如此。函数的调用方式有3种,包括函数语句调用、函数表达式调用、函数参数调用。下面对这3种情况进行介绍。

函数语句调用

把函数的调用作为一个语句就叫函数语句调用。函数语句调用是最常使用的调用函数的方式,如下所示:

Display();  /*显示一条消息*/

这个函数的功能就是在函数的内部显示一条消息。这时不要求函数带返回值,只要求完成一定的操作。

【实例9.11】 函数语句调用。本实例使用语句调用函数方式,通过调用函数完成显示一条信息的功能,进而观察函数语句调用的使用方式。


  
  1. #include<stdio.h>
  2. void Display() /*定义函数*/
  3. {
  4. printf("Just show this message.");/*实现显示一条信息功能*/
  5. }
  6. int main()
  7. {
  8. Display(); /*函数语句调用*/
  9. return 0; /*程序结束*/
  10. }

函数表达式调用

函数出现在一个表达式中,这时要求函数带回一个确定的值,这个值作为参加表达式的运算。如下述代码所示:

iResult=iNum3*AddTwoNum(3,5);  /*函数在表达式中*/

可以看到,函数AddTwoNum在这条语句中的功能是使两个数相加。在表达式中,AddTwoNum将相加的结果与iNum3变量执行乘法,将得到的结果赋值给iResult变量。

【实例9.12】 函数表达式调用。在本实例中,定义一个函数,函数的功能是进行加法计算,并在表达式中调用该函数,使得函数的返回值参加运算得到新的结果。


  
  1. #include<stdio.h>
  2. /*声明函数,函数进行加法计算*/
  3. int AddTwoNum(int iNum1, int iNum2);
  4. int main()
  5. {
  6. int iResult; /*定义变量用来存储计算结果*/
  7. int iNum3=10; /*定义变量,赋值为10*/
  8. iResult=iNum3*AddTwoNum(3,5); /*在表达式中调用函数AddTwoNum*/
  9. printf("The result is : %d\n",iResult); /*将计算结果进行输出*/
  10. return 0;/*程序结束*/
  11. }
  12. int AddTwoNum(int iNum1, int iNum2)/*定义函数*/
  13. {
  14. int iTempResult; /*定义整型变量*/
  15. iTempResult=iNum1+iNum2;/*进行加法计算,并将结果赋值给iTempResult*/
  16. return iTempResult; /*返回计算结果*/
  17. }

函数参数调用

函数调用作为一个函数的实参,这样将函数返回值作为实参传递到函数中使用。

函数出现在一个表达式中,这时要求函数带回一个确定的值,这个值用作参加表达式的运算。如下代码所示:

iResult=AddTwoNum(10,AddTwoNum(3,5));/*函数在参数中*/

在这条语句中,函数AddTwoNum的功能还是进行两个数相加。AddTwoNum将相加的结果作为函数的参数,继续进行计算。

【实例9.13】 函数参数调用。本实例在前面程序的基础上进行修改,进行连续加法的操作。


  
  1. #include<stdio.h>
  2. /*声明函数,函数进行加法计算*/
  3. int AddTwoNum(int iNum1, int iNum2);
  4. int main()
  5. {
  6. int iResult;/*定义变量用来存储计算结果*/
  7. iResult=AddTwoNum(10,AddTwoNum(3,5)); /*在参数中调用函数AddTwoNum*/
  8. printf("The result is : %d\n",iResult);/*将计算结果进行输出*/
  9. return 0; /*程序结束*/
  10. }
  11. int AddTwoNum(int iNum1, int iNum2)/*定义函数*/
  12. {
  13. int iTempResult; /*定义整型变量*/
  14. iTempResult=iNum1+iNum2; /*进行加法计算,并将结果赋值给iTempResult*/
  15. return iTempResult; /*返回计算结果*/
  16. }

嵌套调用

在C语言中,函数的定义都是互相平行、独立的,也就是说在定义函数时,一个函数体内不能包含定义的另一个函数,这一点和PASCAL语言是不同的(PASCAL允许在定义一个函数时,在其函数体内包含另一个函数的定义,而这种形式称为嵌套定义)。例如,下面的代码是错误的:


  
  1. int main()
  2. {
  3. void Display() /*错误!!!不能在函数内定义函数*/
  4. {
  5. printf("I want to show the Nesting function");
  6. }
  7. return 0;
  8. }

递归调用

C语言的函数都支持递归,也就是说,每个函数都可以直接或者间接地调用自己。所谓的间接调用,是指在递归函数调用的下层函数中再调用自己。递归关系如图所示。

递归之所以能实现,是因为函数的每个执行过程在栈中都有自己的形参和局部变量的副本,这些副本和该函数的其他执行过程不发生关系。

【实例9.15】 函数的递归调用。本实例中,定义一个字符串数组,为其数组赋值为一系列的名称,通过递归函数的调用,最后实现逆序显示排列的名单。


  
  1. #include<stdio.h>
  2. void DisplayNames(char** cNameArray); /*声明函数*/
  3. char* cNames[]= /*定义字符串数组*/
  4. {
  5. "Aaron", /*为字符串进行赋值*/
  6. "Jim",
  7. "Charles",
  8. "Sam",
  9. "Ken",
  10. "end" /*设定结束标志*/
  11. };
  12. int main()
  13. {
  14. DisplayNames(cNames); /*调用递归函数*/
  15. return 0;
  16. }
  17. void DisplayNames(char** cNameArray)
  18. {
  19. if(*cNameArray=="end")/*判断结束标志*/
  20. {
  21. return ; /*函数结束返回*/
  22. }
  23. else
  24. {
  25. DisplayNames(cNameArray+1);/*调用递归函数*/
  26. printf("%s\n",*cNameArray);/*输出字符串*/
  27. }}

内部函数和外部函数

内部函数

定义一个函数,如果希望这个函数只被所在的源文件使用,那么就称这样的函数为内部函数。内部函数又称为静态函数。使用内部函数,可以使函数只局限在函数所在的源文件中,如果在不同的源文件中有同名的内部函数,则这些同名的函数是互不干扰的。

在定义内部函数时,要在函数返回值和函数名前面加上关键字static进行修饰:

static  返回值类型  函数名  (参数列表)

例如定义一个功能是进行加法运算且返回值是int型的内部函数,代码如下:

static int Add(int iNum1,int iNum2)

在函数的返回值类型int前加上关键字static,就将原来的函数修饰成内部函数。

【实例9.16】 内部函数的使用。在本函数中使用内部函数,通过一个函数对字符串进行赋值,再通过一个函数对字符串进行输出显示。


  
  1. #include<stdio.h>
  2. static char* GetString(char* pString) /*定义赋值函数*/
  3. {
  4. return pString; /*返回字符*/
  5. }
  6. static void ShowString(char* pString) /*定义输出函数*/
  7. {
  8. printf("%s\n",pString);/*显示字符串*/
  9. }
  10. int main()
  11. {
  12. char* pMyString; /*定义字符串变量*/
  13. pMyString=GetString("Hello!"); /*调用函数为字符串赋值*/
  14. ShowString(pMyString); /*显示字符串*/
  15. return 0;
  16. }

外部函数

与内部函数相反的就是外部函数,外部函数是可以被其他源文件调用的函数。定义外部函数使用关键字extern进行修饰。在使用一个外部函数时,要先用extern声明所用的函数是外部函数。

例如函数头可以写成下面的形式:

extern int Add(int iNum1,int iNum2);

这样,函数Add就可以被其他源文件调用进行加法运算。

【实例9.17】 外部函数的使用。在本实例中,使用外部函数完成和上述实例中使用内部函数时相同的功能,只是所用的函数不包含在同一个源文件中。


  
  1. /* ExternFun.c*/
  2. #include<stdio.h>
  3. extern char* GetString(char* pString);/*声明外部函数*/
  4. extern void ShowString(char* pString);/*声明外部函数*/
  5. int main()
  6. {
  7. char* pMyString; /*定义字符串变量*/
  8. pMyString=GetString("Hello!"); /*调用函数为字符串赋值*/
  9. ShowString(pMyString); /*显示字符串*/
  10. return 0;
  11. }
  12. /*ExternFun1.c*/
  13. extern char* GetString(char* pString)
  14. {
  15. return pString; /*返回字符*/
  16. }
  17. /* ExternFun2.c */
  18. extern void ShowString(char* pString)
  19. {
  20. printf("%s\n",pString);/*显示字符串*/
  21. }

局部变量与全局变量

局部变量

在一个函数的内部定义的变量是局部变量。上述实例中绝大多数的变量都只是局部变量,这些变量声明在函数内部,无法被别的函数所使用。函数的形式参数也是属于局部变量,作用范围仅限于函数内部的所有语句块。

不同情况下局部变量的作用域范围。

【实例9.18】 局部变量的作用域。本实例在不同的位置定义一些变量,并为其赋值来表示变量的所在位置,最后输出显示其变量值,通过输出的信息来观察局部变量的作用范围。


  
  1. #include<stdio.h>
  2. int main()
  3. {
  4. int iNumber1=1; /*iNumber1的作用域在整个main函数中*/
  5. if(iNumber1>0)
  6. {
  7. int iNumber2=2;/*iNumber2的作用域在if语句块中*/
  8. if(iNumber2>0)
  9. {
  10. int iNumber3=3;/*iNumber3的作用域在if语句块中*/
  11. /*将3个都在此作用域的函数进行输出*/
  12. printf("All three number are in scope here %d %d %d\n",
  13. iNumber1,iNumber2,iNumber3);
  14. }
  15. }
  16. return 0;
  17. }

【实例9.19】 局部变量的屏蔽作用。本实例中,在不同的语句块中定义3个相同名称的变量,通过输出变量值来演示有关局部变量的屏蔽作用效果。


  
  1. #include<stdio.h>
  2. int main() /*主函数main中*/
  3. {
  4. int iNumber1=1; /*在第一个iNUmber1定义位置*/
  5. printf("%d\n",iNumber1);/*输出变量值*/
  6. if(iNumber1>0)
  7. {
  8. int iNumber1=2;/*在第二个iNUmber1定义位置*/
  9. printf("%d\n",iNumber1);/*输出变量值*/
  10. if(iNumber1>0)
  11. {
  12. int iNumber1=3; /*在第3个iNUmber1定义位置*/
  13. printf("%d\n",iNumber1);/*输出变量值*/
  14. }
  15. printf("%d\n",iNumber1);/*输出变量值*/
  16. }
  17. printf("%d\n",iNumber1); /*输出变量值*/
  18. return 0;
  19. }

全局变量

程序的编译单位是源文件,通过上文的介绍可以了解到在函数中定义的变量称为局部变量。如果一个变量在所有函数的外部声明,这个变量就是全局变量。顾名思义,全局变量是可以在程序中的任何位置进行访问的变量。

定义全局变量的作用是增加函数间数据联系的渠道。由于同一个文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就能影响到其他函数,相当于各个函数间有直接传递通道。

例如,有一家全国连锁商店机构,商店所使用的价格是全国统一的。全国各地有很多这样的连锁商店,当进行价格调整的时候,应该确保每一家连锁商店的价格是相同的。全局变量就像其中所要设定的价格,而函数就像每一家连锁店,当全局变量进行修改的时候,那么函数中使用的该变量都被更改。

函数应用

为了使用户快速编写程序,编译系统都会提供一些库函数,不同的编译系统所提供的库函数可能不完全相同。其中可能函数名称相同但是实现的功能不同,也有可能实现统一功能但是函数的名称却不同。ANSI C标准建议提供的标准库函数包括了目前多数C编译系统所提供的库函数,下面就介绍一部分常用的库函数。

在程序中经常会使用一些数学的运算或者公式,这里首先介绍有关数学的常用函数。

abs函数

函数的功能是:求整数的绝对值。函数定义如下:

int abs(int i);

例如求一个负数的绝对值的方法:

int iAbsoluteNumber;  /*定义整数*/

int iNumber = -12;  /*定义整数,为其赋值为-12*/

iAbsoluteNumber=abs(iNumber);  /*将iNumber的绝对值赋给iAbsoluteNumber变量*/

labs函数

函数的功能是:求长整数的绝对值。函数定义如下:

long labs(long n);

例如求一个长整型的绝对值的方法:

long lResult;  /*定义长整型*/

long lNumber = -1234567890L;   /*定义长整型,为其赋值为-1234567890*/

lResult= labs(lNumber);  /*将lNumber的绝对值赋给iResult变量*/

fabs函数

函数的功能是:返回浮点数的绝对值。函数定义如下:

double fabs(double x);

例如求一个实型的绝对值的方法:

double fFloatResult;  /*定义实型变量*/

double fNumber = -1234.0;   /*定义实型变量,为其赋值为-1234.0*/

fFloatResult= fabs(fNumber);  /*将fNumber的绝对值赋给fResult变量*/

【实例2.21】 数学库函数使用。在本实例中,将上述介绍的3个库函数放在一起,通过调用函数,观察函数的作用。


  
  1. #include<stdio.h>
  2. #include<math.h> /*包含头文件math.h*/
  3. int main()
  4. {
  5. int iAbsoluteNumber;/*定义整数*/
  6. int iNumber = -12; /*定义整数,为其赋值为-12*/
  7. long lResult; /*定义长整型*/
  8. long lNumber = -1234567890L; /*定义长整型,为其赋值为-1234567890*/
  9. double fFloatResult;/*定义浮点型*/
  10. double fNumber = -123.1; /*定义浮点型,为其赋值为-1234.0*/
  11. iAbsoluteNumber=abs(iNumber);/*将iNumber的绝对值赋给iAbsoluteNumber变量*/
  12. lResult= labs(lNumber); /*将lNumber的绝对值赋给iResult变量*/
  13. fFloatResult= fabs(fNumber); /*将fNumber的绝对值赋给fResult变量*/
  14. /*输出原来的数字,然后将得到的绝对值进行输出*/
  15. printf("the original number is: %d, the absolute is: %d\n",iNumber,iAbsoluteNumber);
  16. printf("the original number is: %ld, the absolute is: %ld\n",lNumber,lResult);
  17. printf("the original number is: %lf, the absolute is: %lf\n",fNumber,fFloatResult);
  18. return 0;
  19. }

sin函数

函数的功能是:正弦函数。函数定义如下:

double sin(double x);

例如求正弦值的方法:

double fResultSin;  /*定义实型变量*/

double fXsin = 0.5;   /*定义实型变量,并进行赋值*/

fResultSin = sin(fXsin);   /*使用正弦函数*/

 

cos函数

函数的功能是:余弦函数。函数定义如下:

double cos(double x);

例如求余弦值的方法:

double fResultCos;  /*定义实型变量*/

double fXcos = 0.5;   /*定义实型变量,为其赋值为0.5*/

fResultCos = cos(fXcos);  /*调用余弦函数*/

tan函数

函数的功能是:正切函数。函数定义如下:

double tan(double x);

例如求正切值的方法:

double fResultTan;   /*定义实型变量*/

double fXtan = 0.5;  /*定义实型变量,为其赋值为0.5*/

fResultTan = tan(fXtan);  /*调用正切函数*/

isalpha函数

函数的功能是:检测字母,如果参数(ch)是字母表中的字母(大写或小写),则返回非零。要包含头文件ctype.h。函数定义如下:

int isalpha( int ch );

例如判断输入的字符是否为字母的方法:

char c;  /*定义字符变量*/

scanf( "%c", &c );  /*输入字符*/

isalpha(c);  /*调用isalpha函数判断输入的字符*/

 

isdigit函数

函数的功能是:检测数字,如果ch是数字则函数返回非零值,否则返回零。要包含头文件ctype.h。函数定义如下:

int isdigit( int ch );

例如判断输入的字符是否为数字的方法:

char c;  /*定义字符变量*/

scanf( "%c", &c );  /*输入字符*/

isdigit(c);  /*调用isdigit函数判断输入的字符*/

isalnum函数

函数的功能是:检测字母或数字,如果参数是字母表中的一个字母或是一个数字,则函数返回非零值,否则返回零。要包含头文件ctype.h。函数定义如下:

int isalnum( int ch );

例如判断输入的字符是否为数字或字母的方法:

char c;  /*定义字符变量*/

scanf( "%c", &c );  /*输入字符*/

isalnum(c);  /*调用isalnum函数判断输入的字符*/

每文一语

诗酒趁年华

文章来源: wxw-123.blog.csdn.net,作者:王小王-123,版权归原作者所有,如需转载,请联系作者。

原文链接:wxw-123.blog.csdn.net/article/details/118342230

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。