预处理命令

来源:互联网 发布:腾讯视频怎么没有mac版 编辑:程序博客网 时间:2024/06/04 19:43

一、宏定义

 编译预处理是指一些行首以#开头的特殊语句,必须在对程序进行通常的编译之前,先对程序中这些特殊的命令进行“预处理”,即根据预处理命令对程序作相应的处理(例如,若程序中用# define命令定义了一个符号常量A,则在预处理时将程序中所有的A都置换为指定的字符串)。经过预处理后程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。C语言与其它高级语言的一个重要区别是可以使用预处理命令和具有预处理的功能。

C提供的预处理功能主要有以下三种:宏定义、文件包含和条件编译

它们分别用宏定义命令、文件包含命令和条件编译命令来实现。为了与一般C语句相区别,这些命令以符号“#”开头。

宏定义指的是用#define定义的命令行,有不带参数和带参数两种形式

1、不带参数的宏定义
不带参数的宏定义的一般形式为:
          # define  标识符  字符串
含义是用指定的宏名(即标识符)来代表其后字符串

例如:
         #define  SIZE  10000
         #define  PI  3.1415926
         #define  FORMAT  “%d,%d,%d\n”
作用是指用标识符SIZE来代替字符串“10000”,
用标识符PI来代替字符串“3.1415926”,
用标识符FORMAT来代替字符串“ “%d,%d,%d\n” ”,

            在编译预处理时,将程序中在该命令以后出现的所有的SIZE用10000代替、PI用3.1415926代替、FORMAT用“%d,%d,%d\n”代替。这种方法使用户能以一个简单的名字代替一个长的字符串,可以减小重复编程工作量,而且不容易出错。

 把定义时所用的标识符称为“宏名”,即SIZE、PI和FORMAT都是宏名。在预编译时将宏名替换成字符串的过程称为“宏展开”。
注意:宏名习惯用大写字母表示。定义宏与定义变量含义不同,宏定义只是作字符替换,并不给宏名分配内存空间。

对宏定义的说明:
     (1)定义宏的目的是提高程序的可读性和通用性,便于程序的修改。例如若要把例8.1中数组data的元素个数改变为10,则只要将“#define SIZE 5”改为“#define SIZE 10”即可,程序中的其它语句均不用修改。
    (2)不要在宏定义的行末加分号,因为宏定义不是C语句,加分号后,会将分号也作为字符串的组成部分,宏展开后可能出现错误。
    (3)宏定义可以出现在程序的任何位置,一般位于文件开头,写在函数的外面。宏名的有效范围是从定义处到本源文件结束。可以用#undef命令终止宏定义的作用域。

例如:
#define  PI  3.1415926
        int main()
        { …
          #undef  PI
          …
        }
           由于#undef的作用,使PI的作用范围在#undef行处终止。若在#undef PI之后再出现PI,则是无效的。

     (4)宏定义是用宏名代替一个字符串,凡在宏定义有效范围内的宏名都用该字符串代替,但要注意:双引号内的与宏名相同的字符串不认为是宏名,不进行替换。

例如:

#define  I1  30
         #define  I2  60
         #define  J  I1+I2
         #define  K  J*2+J/2+I2
         这里J引用了I1和I2,K引用了J和I2。
         注意K展开是:30+60*2+30+60/2+60,
         不要以为是:(30+60)*2+(30+60)/2+60。
         除非前面的定义是:#define  J  (I1+I2)。

2、带参数的宏定义

带参数的宏定义的一般形式为:
            #define标识符(形参表)  字符串
             带参数的宏展开时,还要进行参数替换。宏定义中形参表中的形参,在程序中将用实参替换。例如:
          #define  PI  3.14159
          #define  V(r)  4*PI*r*r*r/3
       V(r)为带参数的宏,例如在程序中使用V(6)时,是用6代替宏定义中的形式参数r,V(6)展开为:4*3.14159*6*6*6/3,这是用来计算半径为6的球的体积。

在使用带参数的宏定义时,宏名和括号之间不能有空格,否则系统会把括号、形参和字符串认为是一个字符串。

带参数的宏和函数在形式上有相似的地方,但是它们有许多不同点:
      (1)宏展开是在编译时进行的,不占用程序运行时间,在展开时并不分配内存单元,即使是带参数的宏也不分配内存单元;而函数调用则是在程序运行时进行处理的,占用程序运行时间,要为形参分配临时的内存单元。
      (2) 宏展开只是替换;而函数调用时,要计算实参表达式的值后传递给形参,不是替换。函数调用时存在着从实参向形参传递数据的过程,而使用带参数的宏,也不存在传递数据的过程。
      (3)宏名以及它的参数都不存在类型问题,展开时用指定的字符串替换即可。而函数中的实参和形参都要定义类型。
            (4)宏展开后对源程序长度有影响,而函数调用对源程序长度无影响。

二、“文件包含”处理
 C语言提供了# include命令用来实现“文件包含”的操作。作用是将一个源文件的全部内容包含进另一个源文件中来。
      被包含的文件可以是C语言源文件、库函数头文件等。因为# include命令行通常都放在文件的开头,所以这些被包含的文件通常被称为“标题文件”或“头文件”,常以“.h”(h为head的缩写)为文件的扩展名。当然也可以用其他文件扩展名,但无论用什么扩展名,这个被包含文件必须是文本文件。
       C集成环境为用户提供了很多库函数,每一个库函数都有自己对应的头文件,在C语言库函数与用户程序之间进行信息通信时,要使用一些库函数中定义的数据和变量,在使用某一库函数时,都要在程序中使用# include命令将该函数所对应的头文件包含进来,否则,程序在编译时报错。
  文件包含的使用格式为:
          #include  “文件名”   
或   #include  <文件名>
   其中的“文件名”和<文件名>的区别是:当使用“文件名” 形式时,预处理程序首先检索当前文件目录是否有该文件,如果没有,再检索C编译系统中指定的目录;而使用<文件名>形式时,预处理程序直接检索C编译系统指定的目录。使用“”时,格式文件包含名可加路径。

常用的标准库头文件的扩展名都是h,如:
# include  <stdio.h>  /*标准输入输出函数文件*/
# include  <string.h>  /*字符串函数文件*/
# include  <ctype.h>  /*字符函数文件*/
# include  <math .h>       /*数学函数库文件*/

三、条件编译 

 1、#   ifdef   标识符   
              程序段1
       #   else
              程序段2
       #    endif

2、 #   ifndef   标识符
              程序段1
      #   else
              程序段2
      #   endif

3、 #   if   表达式
              程序段1
       #   else
              程序段2
       #    endif

原创粉丝点击