[ 随手记 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))

上一篇:P1407 [国家集训队]稳定婚姻


下一篇:HDU5618 & CDQ分治