C语言基础(二):预处理命令

预处理

所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。

C语言提供了多种预处理功能,如宏定义(#define)、文件包含(#include)、条件编译(#ifdef)等。合理地使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。

无参宏定义

在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏“。在C语言中,“宏”分为有参数和无参数两种。无参宏的宏名后不带参数。其定义的一般形式为:#define 标识符 字符串

#define M (y*y+3*y)

它的作用是指定标识符M来代替表达式(yy+3y)。

#include "stdio.h"
#define M (y*y+3*y)
int main(void){
    int s,y;
    printf("input a number:  ");
    scanf("%d",&y);
    s=3*M+4*M+5*M;
    printf("s=%d\n",s);
    return 0;
}

上例程序中首先进行宏定义,定义M来替代表达式(yy+3y),在s=3M+4M+5* M中作了宏调用。在预处理时经宏展开后该语句变为:

s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y);

带参宏定义

C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。带参宏定义的一般形式为:#define 宏名(形参表) 字符串 在字符串中含有各个形参。

带参宏调用的一般形式为: 宏名(实参表);

【例】输出两个数中较大的数。

#include "stdio.h"
#define MAX(a,b) (a&gtb) ? a : b
int main(void){
    int x,y,max;
    printf("input two numbers:");
    scanf("%d%d",&x,&y);
    max=MAX(x,y);
    printf("max=%d\n",max);
    return 0;
}

上例程序的第一行进行带参宏定义,用宏名MAX表示条件表达式(a>b)?a:b,形参a、b均出现在条件表达式中。程序第6行max=MAX(x,y)为宏调用,实参x、y,将代换形参a、b。宏展开后该语句为:

max=(x&gty) ? x : y;

用于计算x、y中的大数。

文件包含

文件包含命令行的一般形式为: #include "文件名"

在前面我们已多次用此命令包含过库函数的头文件。例如:

#include "stdio.h&quot
#include "math.h&quot

文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。

在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。

ifdef的形式

预处理程序提供了条件编译的功能。条件编译有三种形式,下面分别介绍。

第一种形式

第一种形式的格式为:

#ifdef 标识符 程序段1

  #else
        程序段2
  #endif

功能是,如果标识符已被 #define命令定义过则对程序段1进行编译;否则对程序段2进行编译。如果没有程序段2(它为空),本格式中的#else可以没有,即可以写为:

#ifdef 标识符 程序段
 #endif
#include "stdio.h"
#define NUM ok
int main(void){
    struct stu{
        int num;
        char *name;
        char sex;
        float score;
    } *ps;
    ps=(struct stu*)malloc(sizeof(struct stu));
    ps-&gtnum=102;
    ps-&gtname="Zhang ping";
    ps-&gtsex='M';
    ps-&gtscore=62.5;
    #ifdef NUM
        printf("Number=%d\nScore=%f\n",ps-&gtnum,ps-&gtscore);
    #else
        printf("Name=%s\nSex=%c\n",ps-&gtname,ps-&gtsex);
    #endif
    free(ps);
    return 0;
}

由于在程序的第15行插入了条件编译预处理命令,因此要根据NUM是否被定义过来决定编译那一个printf语句。而在程序的第一行已对NUM作过宏定义,因此应对第一个printf语句作编译故运行结果是输出了学号和成绩。

第二种形式

第二种形式的格式为:

#ifndef 标识符 程序段1

 #else
    程序段2
 #endif

与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是,如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。这与第一种形式的功能正相反。

第三种形式

第三种形式的格式为:

#if 常量表达式 程序段1

 #else
        程序段2
 #endif

它的功能是,如常量表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能。

#include "stdio.h"
#define R 1
int main(void){
    float c,r,s;
    printf ("input a number:  ");
    scanf("%f",&c);
    #if R
        r=3.14159*c*c;
        printf("area of round is: %f\n",r);
    #else
        s=c*c;
        printf("area of square is: %f\n",s);
    #endif
    return 0;
}

本例中采用了第三种形式的条件编译。在程序第1行宏定义中,定义R为1,因此在条件编译时,常量表达式的值为真,故计算并输出圆面积。

全部评论(0)