C语言学习---09 预处理命令

      C语言属于高级语言,用C语言编写的程序称为源程序。这种用高级语言编写的源程序,是不能被计算机直接识别的,必须用C语言的编译系统把源程序编译成目标程序并连接成可执行程序,才可以被计算机执行。因此,用C语言处理问题,必须经过程序的编辑、编译、连接和运行4个阶段。然而,为了减少C语言源程序编写的工作量,改善程序的组织和管理,帮助程序员编写易读、易改、易于移植、便于调试的程序,C语言编译系统提供了预编译功能。                                                 C语言编译系统提供的编译预处理功能是C语言区别于其他高级语言的特点之一,这对编写大型程序非常有用。编译预处理是指对源程序进行编译之前先调用C语言的预处理程序,即对以“#”开头的命令进行解释、替换,产生一个新的源程序,然后才对源程序进行通常意义下的编译。                  C语言提供的编译预处理功能主要有3种:宏定义、文件包含和条件编译。这3种功能分别以3条编译预处理命令—-#define、#include、#if来实现。编译预处理命令不属于C语言的语法范畴,因此,为了和C语言进行区别,预处理命令都以“#”开头,每条预处理命令必须独占一行且结束时不能使用语句结束符“;”。                                                                                                                                C语言中编译预处理的执行过程如下图所示:

宏定义 

       在C语言中使用宏定义可以提高源程序的可维护性、可移植性,并且可以减少源程序中重复书写字符串的工作量。C语言有两种宏定义命令:不带参数的宏定义和带参数的宏定义。                   

                    不带参数的宏定义                                                                                                                   不带参数的宏定义常用于定义符号常量。所谓不带参数的宏定义指用一个指定的标识符来代表一个字符串。该标识符也称宏名,宏名后面不带圆括号和参数表。其定义的一般格式如下:                      #define  宏名      替换字符                                                                                                              其中,“#”表示这是一条预处理命令,“define”为宏定义命令。                                                            这种方法使得用户能以一个简单易记的常量名称替代一个较长而难记的具体常量。预处理是用具体的常量字符串替换宏名,这个过程称为宏展开。例如:    #define  PI   3.1415926                          该宏定义的作用是指定PI常数“3.1415926”,程序中原来需要使用3.1415926且含义为圆周率的地方,都可以改用PI。这样程序中出现PI的地方,经预处理后都会替换为3.1425926。                         说明:(1)宏名的前后应有空格,以便准确的辨认宏名。如果没有空格,则程序运行的结果会出错。一般用大写字母表示宏名,但用小写字母表示宏名,系统也不认为是错的。                                          (2)宏定义是用宏名来表示一个字符串,在宏名展开时又以该字符串取代宏名。这只是一个简单的代换,字符串中可以含有任何字符,可以是常数,也可以是表达式,预处理程序对他不做任何检查。如果错误,则只能在编译阶段发现。                                                                                            (3)预处理命令不是语句,其后不加分号。                                                                                    (4)字符串(或数值)中如果出现运算符号,则要注意替换后的结果,通常可以在合适的位置加上括号。

                       带参数的宏定义                                                                                                                      带参数的宏定义是指用一个带参数的宏名代表一个字符串,预处理时不仅要进行字符串替换,还要进行参数替换。其定义的一般格式如下:       #define  宏名(参数表)  字符串                             在尾部的替换字符串中一般含有宏名括号中指定的参数。在预处理时,编译器用程序中的实际参数代替宏定义中有关的形式参数。                                                                                                         带参宏调用的一般格式如下:  宏名(实参表)                                                                                 实参可以是常量、变量或表达式。例如,宏定义为:   #define  L(a,b,c)    ((a)*(b)*(c))                     宏调用为:   per=L(3,4,5);                                                                                                                 在预处理时,用实参3,4,5替代形参a、b、c,宏展开后得到:                                                                     per=( (3)*(4)*(5) );                                                                                                               注意:这里字符串中的形参加括号是非常必要的。如果去掉形参左右的括号,则可能导致结果不准确。                                                                                                                                                      从参数替换的角度看,宏定义与函数类似,都是用实参代替形参,但在本质上是不同的:     宏的展开在预处理时进行,而函数在程序执行调用时才起作用;带参数的宏定义只进行简单的字符串替换,没有函数那样的参数运算,既不进行值传递,也没有返回值概念。

                宏替换与函数调用的区别:                                                                                                           (1)在程序控制中,当编译预处理时,宏实参只是简单地对宏形参进行原型替换;当调用函数时,则是先求出实参表达式的值,再代入形参变量中。                                                                             (2)与函数的参数不同,宏参数没有固定的数据类型,因此宏定义时不涉及类型,宏名和宏参数均无类型。                                                                                                                                            (3)函数调用是在程序运行时发生的,并动态分配所用的内存单元;而宏替换是在编译预处理时进行的,且不分配内存单元,不进行值传递,也无值返回。                                                                   (4)使用函数调用不增加运行的长度:而每使用一次宏替换,都会使运行程序篇幅有所增长,也会使编译、连接后的执行程序增长。                                                                                                      (5)宏定义主要用于需要少量参数的简单表达式,而且调用时不做数据类型检查。

文件包含

        文件包含是指在一个文件中包含另一个文件的全部内容,即#include命令行被所包含文件的内容覆盖,当一个文件的内容被其他文件重复使用时很有用。                                                                     文件包含命令的格式如下:(1)用一对尖括号括起被包含源文件的名称。  #include <文件名>               (2)用一对双引号括起被包含源文件的名称。#include"文件名”                                                            其中,文件名允许是C语言编译系统提供的预定义文件名或用户自己定义的C语言程序名。例如:#include<stdio.h>      #include"file.c"                                                                                          stdio.h就是C语言预定义的标准头文件,而file.c则是用户自定义的C语言程序文件。两种文件包含命令的区别:#include<文件名>方式常用于包含系统头文件。系统头文件一般存储在系统指定的目录中,当C语言编译器识别这条#include<文件名>命令后,它不搜索当前子目录,而是直接到系统指定的包含子目录(即include子目录)中去搜索相应的头文件,并将头文件的内容“包含”到“主”文件中。例如:#include<string.h>                                                                                                                 编译系统仅在设定的子目录下查找包含文件,如果找不到,编译系统将会报告错误信息,并停止编译过程。                                                                                                                                           #include"文件名”方式常用来“包含”程序员自己建立的头文件。当C语言编译器识别出这条#include"文件名"命令后,它先搜索“主”文件所在的当前子目录,如果没有找到,再去搜索相应的系统子目录。例如:#include  "c:\user\user.h"                                                                                               编译系统在c:luser子目录下查找被包含的文件user.h。                                                                      C语言也允许一个被包含文件中又包含另一个被包含文件,即文件包含是可以嵌套的。                      说明:(1)一条#include命令只能包含一个文件,若要包含多个文件就必须使用多条#include命令。                                                                                                                                          (2)C语言提供了若干个标准函数库,每个标准函数库都与某个预定义的头文件相对应。用户编写程序是可以直接调用被包含文件中的程序而不必自己编写。                                                            (3)除了预定义的标准头文件外,一般情况下包含用户自己设计的文件。                                     (4)当用户文件由多个源程序文件组成时,为了避免重复性的说明和定义,提高程序编写的效率和程序的可靠性、可维护性,可以把各个源文件共同使用的函数类型说明以及符号常量的宏定义等组建为单独的用户包含文件,然后在各个源文件中用#include指定该用户的包含文件。这样不但使程序简洁,而且保证了各个源程序文件中函数说明和符号常量定义的一致性。因此,文件包含也是模块程序化设计的手段之一。

条件编译

        C语言属于高级语言,从原理上说,高级语言的源程序应与系统无关,然而对于不同的系统,C语言的源程序存在微小的差别。在用C语言编写程序时,为了提高其应用范围,或提高它的可移植性,C语言的源程序中的一小部分需要针对不同的系统编写不同的代码,这样可使其在某一确定的系统中选择其中有效的代码进行编译。条件编译就是提供这方面功能的预处理指令。                        若干个条件编译指令允许有选择地编译程序中的某些部分,这个过程称为条件编译。条件编译命令有以下几种形式。                                                                                                                                  1.#if指令                                                                                                                                          #if指令的基本含义:若#if指令后的常数表达式为真,则编译#if和#endif之间的程序段,否则跳过这段程序。#endif指令用于表示该语句段的结束。                                                                                    #if指令的一般格式如下:#if常数表达式                                                                                                                                           语句段                                                                                                                                            #endif    

          2. #ifdef和#ifndef指令                                                                                                                       另一种编译方法是使用#ifdef指令和ifndef指令,意思是“如果宏已定义”和“如果宏未定义”。#ifdef的一般格式如下:#ifdef   宏替换名                                                                                                                                                  语句段                                                                                                                                #endif                                                                                                                    如果宏替换名在此之前已经由#define给出了定义,则编译#ifdef和#endif之间的语句;如果宏替换名在此之前未经#define定义,则编译程序段的内容,可用#ifndef指令。                                                #ifndef的一般格式如下:           #ifndef   宏替换名                                                                                                                                  语句段                                                                                                                                            #endif                                                                                             指令#ifdef和#ifndef还可以与#else指令一起使用 。  

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值