zoukankan      html  css  js  c++  java
  • [ 随手记 1 ] C/C++宏,普通函数,内联函数

    函数定义

    C 语言中的函数定义的一般形式如下:

    return_type function_name( parameter list )
    {
       body of the function
    }

    在 C 语言中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:

    • 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void
    • 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
    • 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
    • 函数主体:函数主体包含一组定义函数执行任务的语句。

     

    函数参数

    如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数

    形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

    当调用函数时,有两种向函数传递参数的方式:

    调用类型描述
    传值调用 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。
    引用调用 通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。

    默认情况下,C 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的实际参数。

    ===============================================================

    内联函数的执行过程与带参数宏定义很相似,但参数的处理不同。带参数的宏定义并不对参数进行运算,而是直接替换;内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算求值,然后把表达式的值传递给形式参数。

        内联函数与带参数宏定义的另一个区别是,内联函数的参数类型和返回值类型在声明中都有明确的指定;而带参数宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患。

        使用内联函数时,应注意以下问题:
    1.=====================================================================   

    1)内联函数的定义性声明应该出现在对该函数的第一次调用之前。
        2)内联函数首先是函数,函数的很多性质都适用于内联函数,如内联函数可以重载。
        3)在内联函数中不允许使用循环语句和switch结果,带有异常接口声明的函数也不能声明为内联函数。

    先说宏和函数的区别:
    1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类
    型的,可以是各种各样的类型.

    2. 宏的参数替换是不经计算而直接处理的,而函数调用是将实参的值传递给形参,既然说是值,自然是计算得来的.
    3. 宏在编译之前进行,即先用宏体替换宏名,然后再编译的,而函数显然是编译之后,在执行时,才调用的.因此,宏占用的
    是编译的时间,而函数占用的是执行时的时间.

    4. 宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的.

    5. 函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场,然后转入被调用函数去执行,调用完,再返回主调函数,此时再恢复现场,这些操作,显然在宏中是没有的.

    2.======================================================
    现在来看内联函数:
    所谓"内联函数"就是将很简单的函数"内嵌"到调用他的程序代码中,只样做的目的是为了避免上面说到的第5点,目的旨在节约下原本函数调用时的时空开销. 但必须注意的是:作为内联函数,函数体必须十分简单,不能含有循环、条件、选择等复杂的结构,否则就不能做为内联函数了。事实上,即便你没有指定函数为内 联函数,有的编译系统也会自动将很简单的函数作为内联函数处理;而对于复杂的函数,即便你指定他为内联函数,系统也不会理会的。

      下面我们来介绍一下内联函数的用法。

      内联函数必须是和函数体申明在一起,才有效。像这样的申明

    Inline Tablefunction(int I)是没有效果的,编译器只是把函数作为普通的函

    数申明,我们必须定义函数体。

    Inline tablefunction(int I) {return I*I};

      这样我们才算定义了一个内联函数。我们可以把它作为一般的函数一样调用。但是执行速度确比一般函数的执行速度要快。

      我们也可以将定义在类的外部的函数定义为内联函数,比如:

    Class TableClass{

     Private:

      Int I,j;

     Public:

      Int add() { return I+j;};

      Inline int dec() { return I-j;}

      Int GetNum();

    }

    inline int tableclass::GetNum(){

    return I;

    }

      上面申明的三个函数都是内联函数。在C++中,在类的内部定义了函数体的

    函数,被默认为是内联函数。而不管你是否有inline关键字。

    3.===================================================

    下面我们再来说说内联函数与宏的区别。很多的资料上,在谈到内联函数时就说,内联函数和宏很类似,但是类似归类似,毕竟我们不能把这两者互换使用。

         这两者的相似之处在于执行时编译器对其的处理,会将其代码展开,执行完后继续下面的处理。不同之处在于宏是简单的文本替换,它不能返回值,也没有一般函数参数的概念;而内联函数则具备了普通函数的特征,如参数列表,返回值等。下面我们举个例子说明:

         1.#define COUNT(X)(X * X) // 一个计算乘积的宏
         2.inline int count(int x){return x*x} //一个计算乘积的内联函数
       
         printf(COUNT(3)); // 结果为 COUNT(3) ( 3 * 3) = 9;
         printf(count(3)); // 结果为 count(3){return 3*3 }=9;
       
         上面的例子好象不足以说明两者的区别,我们把上面的例子的调用改改,再看看结果
       
         printf(COUNT(2+3)); //结果为COUNT(2+3)(2+3 * 2+3) = 11
         printf(count(2+3)); //结果为count(2+3){return 5*5 ;} = 25;
       
         如果宏要达到乘积为25的结果,应该这样写:
         #define COUNT(X)((X)*(X))
         对应到上面的例子就是 #define COUNT(2+3)((2+3)*(2+3))

  • 相关阅读:
    零基础学python-16.7 nonlocal介绍
    零基础学python-16.6 嵌套作用域
    零基础学python-16.5 模块间全局变量的修改以及其他访问全局变量的方法
    零基础学python-16.4 global作用域
    零基础学python-16.3 变量名解析:LEGB原则
    如何格式化日期和时间
    如何创建指定的日期和时间
    如何遍历Set对象
    如何遍历Map对象
    如何遍历List对象
  • 原文地址:https://www.cnblogs.com/ggYYa/p/9147412.html
Copyright © 2011-2022 走看看