C语言学习历程(3)——函数

自定义函数

函数是一段可以重复使用的代码,用来独立地完成某个功能,它可以接收用户传递的数据,也可以不接收。
 
一、无参函数的定义
 如果函数不接收用户传递的数据,那么定义时可以不带参数。如下所示:
返回值类型  函数名()
{
    函数体
}
说明:
返回值类型可以是C语言中的任意数据类型,例如 int、float、char、void等。
函数名是标识符的一种,命名规则和标识符相同。函数名后面的括号( )不能少。
函数体是函数需要执行的代码。即使只有一个语句,也要由{ }包围。
注意:1、函数不能嵌套定义,函数必须先定义后使用,所以函数只能在 main 前面。
2、main 是函数定义,不是函数调用。当可执行文件加载到内存后,系统从 main 函数开始执行,也就是说,系统会调用我们定义的 main 函数。
 
二、有参函数的定义
如果函数需要接收用户传递的数据,那么定义时就要带参数。如下所示:
返回值类型  函数名(参数列表)
{
    函数体
}
 用户数据通过“参数列表”传递给函数,供函数处理。
 注意:(1)参数(Parameter)本质上也是变量,定义时要指明参数类型和参数名称。参数列表中可以定义一个或多个参数,多个参数之间用逗号,分隔。列表中的参数可以在函数体内使用。
 (2)函数定义时给出的参数称为形式参数,简称形参;函数调用时给出的参数(传递的数据)称为实际参数,简称实参。函数调用时,将实参的值传递给形参,相当于一次赋值操作。
形参和实参有以下几个特点:
1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。
2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。如:max(10, 20);max(a, b);max(a, 20);
3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。
4)函数调用中发生的数据传送是单向的,只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
 
三、return 语句:函数返回值通过return返回。可以有多个,可以在函数体的任意位置。在函数中,根据 if 的判断结果来执行不同的 return 语句。函数一旦遇到 return 语句就返回(停止执行),后面的所有语句都不会被执行到。也可以不用返回(即无返回值函数void)

局部变量和全局变量

     在 C语言函数的参数和返回值中提到,形参变量要等到函数被调用时才分配内存,调用结束后立即释放内存。这说明形参变量的作用域非常有限,只能在函数内部使用,离开该函数就无效了。所谓作用域(Scope),就是变量的有效范围。不仅对于形参变量,C语言中所有的变量都有自己的作用域。决定变量作用域的是变量的定义位置。
局部变量
      定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。几点说明:
1) 在 main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时,main 函数中也不能使用其它函数中定义的变量。
2) 形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。
3) 可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。
4) 在语句块中也可定义变量,它的作用域只限于当前语句块。
全局变量
     在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。
 注意:1、在局部变量作用的范围内,局部变量有效,全局变量被“屏蔽”不起作用。
2、C语言中的函数只能有一个返回值,以此想要得到函数返回的多个值,可以使用全局变量。

变量的存储方式和生存期

存储方式
      前面已经介绍了,从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。从另一个角度,从变量值存在的时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。
静态存储方式:是指在程序运行期间分配固定的存储空间的方式。
动态存储方式:是在程序运行期间根据需要进行动态的分配存储空间的方式。
 
数据存储类别
     根据数据存储过程和存储位置的不同,将C的存储类别分为4种:自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)。根据变量的存储类别,可以知道变量的作用域和生存期。

  • 自动变量auto

        函数中的局部变量,如不专门声明为 static 存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。如函数中的形参和在函数中定义的变量,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。这类局部变量称为自动变量。自动变量用关键字 auto 作存储类别的声明。关键字 auto 可以省略, auto 不写则隐含定为“自动存储类别”,属于动态存储方式。
 

  • 静态局部变量static

     有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,这时就应该指定局部变量为“静态局部变量”,用关键字 static 进行声明。
注意:1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数调用结束后即释放。
2) 静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
3) 如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值 0 (对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。
 

  • 寄存器变量register

      一般情况下,运算器到内存中存取变量,对于频繁使用的变量,可将局部变量放在 CPU 的寄存器中,运算器对寄存器的读取速度比内存快的多,因此大大提高了效率。这种变量叫“寄存器变量”,用关键字register 作声明。
 
说明:1) 只有局部自动变量和形式参数可以作为寄存器变量;
           2) 一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量
          3)register只向cpu提出申请,但不一定成功。

  • 外部变量extern

      外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字 extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。
1、在一个文件内扩展外部变量的作用域
2、将外部变量的作用域扩展到其他文件
     在任意一个文件中对变量进行定义,在另一个文件中用extern对该变量进行外部声明,就可以在本文件中使用其他文件的定义过的变量了。
注意:编译遇到extern时,先在本文件内找外部变量的定义,如果没有找到再到其他文件寻找该变量的定义。
3、将外部变量的作用域限制在本文件中
     由于一个任务可能由若干人完成,为了防止自己的文件变量被别人引用修改,在外部变量前加static,即将该变量限制在本文件中,其他文件将不能使用该变量。
 
外部函数
     如果定义函数时在函数首部加上extern,该函数为外部函数,可供其他文件调用。当在定义函数时,省略extern,则默认为外部函数。

预处理

在C语言中预定义了一些有用的宏,见表预定义宏。这些宏主要是提供当前编译的信息。
 
表预定义宏:
__TIME__     编译的时间(格式"hh:mm:ss")
__DATE__     编译的日期(格式"Mmm dd yyyy")
__LINE__      被编译的文件的行数
__FILE__      被编译的文件的名字

 


 

 
 

猜你喜欢

转载自blog.csdn.net/Neptune__/article/details/81225881