C-学习笔记5-函数

1.函数的定义

        函数类型 函数名(类型名 形式参数1,类型名 形式参数2 ...)

        {

                说明部分

                语句部分

        }

2.在C语言中,规定函数不允许嵌套定义,即在定义一个函数时,不能在该函数体里包含另一个函数的定义。但是可以嵌套调用,即在一个函数的执行过程中可以调用另一个函数。

3.变量的存储类别及生命周期

       从变量值生存周期来分,可以将变量分为静态存储变量和动态存储变量。静态存储变量是指程序运行时固定分配存储空间的变量。动态储存变量是在程序运行时根据需要动态分配储存空间的变量。

         程序运行时的内存分配有以下5种:系统区、程序代码区、静态数据区、动态数据区、自由空间。全局变量和静态的局部变量存放在静态数据区,在程序开始时给它们分配内存空间,程序执行完毕就释放。在程序执行过程中它们占据固定的存储单元,它们的生命周期贯穿程序的整个过程。

         动态数据存放的数据为自动局部变量、形参变量和中断的现场保护的数据。自动局部变量指的是未加static的局部变量,形式参量指的是函数形式参数,中断的现场保护的数据是指在函数调用的现场保护和返回地址。在函数开始调用是分配动态储存空间,函数结束时释放这些空间,他们的生命周期为函数的整个过程。

           因此,变量完整的定义方式为:储存类别 数据类型标识符 变量名;

          储存类别共有四种:auto——自动变量;static——静态变量;register——寄存器变量;extern——外部变量。

(1).auto变量(自动变量)

          当局部变量定义时使用auto标签或没有指定存储类别时,系统就认为所定义的变量是自动变量。系统对自动变量是动态分配储存空间的,数据存储在动态数据区中。局部变量的定义必须放在函数体或者复合体中所有可执行语句之前。自动变量的作用域是从定义的位置起,到函数体或者复合体结束为止。它的存储单元在进入这些局部变量所在的函数或复合体时生成,退出其所在函数体或复合体时消失,这就是自动变量的生存周期。当再次进入函数体时,系统将为他们另行分配存储单元。

(2).register变量(寄存器变量)

         寄存器变量也是自动变量,它与自动变量的区别仅在于:用register说明的变量建议编译程序将变量的值保留在CPU的寄存器中,而不像一般变量那样,占用内存单元。局部变量的定义必须放在函数体或者复合体中所有可执行语句前。

           说明:

① 只有函数内定义的变量或者形参可以定义为寄存器变量。寄存器变量的值保存在CPU的中。

② 受寄存器长度的限制,寄存器变量只能是char,int和指针类型的变量;对于占用字节数多的变量(long、float、double等)及数组不宜定义为寄存器变量。

③ 由于寄存器变量值保存在CPU的寄存器中,系统从CPU的寄存器中读写变量比内存要快,所以将使用频率比较高的变量设定为寄存器变量。例如for循环中所用到的变量。

④当今的优化编译系统能够识别使用频率较高的变量,从而自动地将这些变量放在寄存器中,因而一般不需要由程序员指定。

注:寄存器是CPU的一部分,寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、地址和数据。

(3).static变量(静态变量)

          a.静态局部变量

         在函数体或内部使用static说明的变量,称静态全局变量。它分配在内存的静态数据存储区。它的生存期与作用域是全局寿命,局部可见。即只有在编译时可以赋值,以后每次调用时不再分配内存单元和初始化,只是保留上一次函数调用结束的值,直到程序运行结束,对应的内存单元才释放,而其作用域仅仅只限于所定义的函数和复合体。  

           注:变量没有赋初值时,auto变量是个随机值,static变量是0。

          例:

          void f1()

          {

                  auto int x = 1;

                  printf("x=%d",x);

          }

          void f2()

          {

                  static int x = 1;

                  x++;

                  printf("x=%d",x);

          }

          int main()

         {

                f1();  f2();

                f1();  f2();

         }

         结果为 x=1 x=2

                     x=1 x=3

         b.静态全局变量

         在所有函数(包括主函数)之外的用static说明的变量,称为静态全局变量。它分配在内存的静态数据存储区,它的生存期与作用域是全局寿命,局部可见。即在整个程序运行期间都存在;但它与外部变量(即全局变量)不同,静态全局变量只能在所定义的文件中使用,具有局部可见性(与静态局部变量的局部可见性不同),而外部变量可在其他文件中使用。

(4).extern变量(外部变量)

        外部变量(即全局变量)是在所有函数(包括主函数)外部定义的变量,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部末尾不在文件开头定义,其有效的作用范围只限于定义处到文件终了。如果定义点之前的函数想引用该外部变量,则应该引用之前用关键字extern对该变量作"外部变量声明"。表示该变量是一个已经定义的外部变量。有了此声明,就可以从"声明"处起,合法地使用该外部变量。

4.外部函数和内部函数

         a.外部函数

              (1).不作任何标示的函数,允许被其他源程序文件中的函数调用;但必须在调用的源文件中做外部函数声明,即在声明时加上extern关键字。

             extern 函数类型 函数名(数据类型 形式参数1,数据类型 形式参数2,...)

              (2).在定义函数时,在函数的首位加上extern关键字,表示该函数是外部函数,可以被其他的文件调用。

             extern 函数类型 函数名(数据类型 形式参数1,数据类型 形式参数2,... ) 

             {

                     函数体

             }

             外部函数的调用方式

             file1.c                                                 file2.c

             extern int function1()                          a = function1();

      或

             int function1()                                    extern int function1();

                                                                       a = function1();

      b.内部函数

            如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其他文件中的函数调用,这种函数称为内部函数。

            内部函数是用static标示的函数,只能被本源程序文件中的函数调用,定义形式为:

             static 函数类型 函数名(数据类型 形式参数1,数据类型 形式参数2,... ) 

             {

                     函数体

             }

5.编译预处理

        编译预处理对源程序编译之前做一些处理:生成扩展C源程序。

        1.编译预处理种类

            宏定义       #define

            文件包含   #include

            条件编译   #if-#else-#endif

         2.带参的宏定义

            #define POWER(x) x*x

带参的宏定义和函数之间的联系与区别
  带参宏 函数
处理时间 编译时 程序运行时
参数类型 无类型问题 定义实参,形参类型
处理过程

不分配内存

简单的字符置换

分配内存先求实参值

再代入形参

程序长度 变长 不变
运行速度 不占运行时间 调用和返回占时间

6.注:

       ① 每个函数都有堆栈区。堆栈区是计算机的内存用来储存函数的变量和参数。

       ② 递归函数必须定义出口,否则会导致系统死机

猜你喜欢

转载自blog.csdn.net/Kayaobi/article/details/82718023