[C++]函数与编译预处理(二)

本文介绍了C++中的参数可变的函数,包括使用`stdarg.h`中的`va_start`、`va_arg`和`va_end`函数处理可变参数。还讨论了函数的重载原则,以及编译预处理的三个方面:宏定义、文件包含和条件编译。此外,提到了程序的多文件组织和内部函数、外部函数的概念。
摘要由CSDN通过智能技术生成

函数与编译预处理

参数个数可变的函数

到目前为止,在定义函数时,都明确规定了函数的参数个数及类型。在调用函数时,实参的个数必须与形参相同。在调用具有缺省参数值的函数时,本质上,实参的个数与形参的个数仍是相同的,由于参数具有缺省值,因此,在调用时可省略。在某些应用中,在定义函数时,并不能确定函数的参数个数,参数的个数在调时才能确定。在C++中允许定义参数个数可变的函数。

 

首先,必须包含头文件“stdarg.h”,因为要用到里面的三个库函数  va_start( )、va_arg( )和va_end( )。

其次,要说明一个va_list类型的变量。va_list与int,float类同,它是C++系统预定义的一个数据类型(非float),只有通过这种类型的变量才能从实际参数表中取出可变有参数。如:va_list   ap;

va_start(ap,b):初始化

va_arg(ap,int):依次取参数

va_end(ap):正确结束

 

va_start():有两个参数,va_start(ap,b); b即为可变参数前的最后一个确定的参数。

va_arg():有两个参数,va_arg(ap,int)    int即为可变参数的数据类型名。

int  temp;

temp=va_arg(ap,int);

va_end():完成收尾工作。va_end(ap);

在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数。如第一个参数值为总的实际参数的个数。

 

使用参数数目可变的函数时要注意以下几点:

1、在定义函数时,固定参数部分必须放在参数表的前面,可变参数在后面,并用省略号“...”表示可变参数。在函数调用时,可以没有可变的参数。

2、必须使用函数va_start()来初始化可变参数,为取第一个可变的参数作好准备工作;使用函数va_arg()依次取各个可变的参数值;最后用函数va_end()做好结束工作,以便能正确地返回。

3、在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数。

函数的重载

所谓函数的重载是指完成不同功能的函数可以具有相同的函数名。

C++的编译器是根据函数的实参来确定应该调用哪一个函数的。

1、定义的重载函数必须具有不同的参数个数,或不同的参数类型。只有这样编译系统才有可能根据不同的参数去调用不同的重载函数。

2、仅返回值不同时,不能定义为重载函数。即仅函数的类型不同,不能定义为重载函数

 

编译预处理

高级语言编译过程

 

C语言提供的编译预处理的功能有以下三种:

宏定义    文件包含     条件编译

 

宏定义

不带参数的宏定义

用一个指定的标识符(即名字)来代表一个字符串,以后凡在程序中碰到这个标识符的地方都用字符串来代替。

这个标识符称为宏名,编译前的替代过程称为“宏展开”。

# define    标识符     字符串

#define  PRICE   30  

void main(void)

{    int  num, total;  /*定义变量*/

      num=10;        /*变量赋值*/

     total=num*PRICE;

     cout<<"total=“<<total<<endl;

}

编译程序将宏定义的内容认为是字符串,没有任何实际的物理意义。

注意:

1、宏展开只是一个简单的“物理”替换,不做语法检查,不是一个语句,其后不加分号“;”

2、#define命令出现在函数的外面,其有效范围为定义处至本源文件结束。可以用# undef命令终止宏定义的作用域。

#define G  9.8

void main(void )

{.....}

# undef   G

int max(int a,int b)

{...... }

3、对程序中用双引号括起来的字符串内容,即使与宏名相同,也不进行置换。

4、在进行宏定义中,可以用已定义的宏名,进行层层置换。

 

带参数的宏定义

 

按#define命令行中指定的字符串从左至右进行置换宏名,字符串中的形参以相应的实参代替,字符串中的非形参字符保持不变。

 

定义宏时在宏名与带参数的括弧间不能有空格。

#define  S_ (r)   P*r*r

带参数的宏与函数调用的区别

相同:有实参、形参,代入调用。

不同之处

1、函数调用先求表达式的值,然后代入形参,而宏只是机械替换。

2、函数调用时形参、实参进行类型定义,而宏不需要,只是作为字符串替代。

3、函数调用是在运行程序时进行的,其目标代码短,但程序执行时间长。而宏调用是在编译之前完成的,运行时已将代码替换进程序中,目标代码长,执行时间稍快。

一般用宏表示实时的、短小的表达式。

 

文件包含

一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中。

#  include   “文件名”

 

注意:

1、文件名是C的源文件名,是文本文件,后缀名可以任选。*.cpp *.h

2、一个#include语句只能指定一个被包含文件。

3、文件名用双引号或尖括号括起来。

4、包含后所有源文件编译为一个可执行文件。

 

条件编译

C语言允许有选择地对程序的某一部分进行编译。也就是对一部分源程序指定编译条件。

 

条件编译有以下几种形式:

1、  # ifdef      标识符

         程序段1

     # else

         程序段2

      # end if

当标识符已被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2.

2、  # ifndef      标识符

            程序段1

     # else

            程序段2

     # endif

与形式1相反,当标识符没有被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2。

3、 # if     表达式

          程序段1

    # else

          程序段2

# endif  

当表达式为真(非零),编译程序段1,表达式为零,编译程序段2。

 

程序的多文件组织

而在设计一个功能复杂的大程序时,为了便于程序的设计和调试,通常将程序分成若干个模块,把实现一个模块的程序或数据放在一个文件中。当一个完整的程序被存放在多于一个文件中时,称为程序的多文件组织。

 

内部函数和外部函数

内部函数:函数只限于在本文件中调用,其它文件不能调用,用static 定义该函数。

static  float  fac( int  n)

{   ......      }

外部函数:函数的默认形式,可以被其它文件调用,用extern 定义该函数。调用时,在文件中用extern 说明。

void main(void)

{  extern  enter_string( );

    char   str[80];

    enter_string(str);

    ..........

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值