C编译预处理宏

来源:互联网 发布:祝利荣牛熊线指标源码 编辑:程序博客网 时间:2024/05/16 18:30

一、编译预处理

作用:对源程序编译之前做一些处理,生成扩展C源程序
种类
宏定义         #define  #ifdef  #ifndef
文件包含      #include
条件编译      #if--#else--#endif等
其他宏定义  #line #error  #pragma
格式:    “#”开头

占单独一行

句末不用加分号


1-2 宏定义 

无参数宏定义
有参数宏定义
#undef

不带参数宏定义
一般形式:   #define   宏名    [宏体]
功能:用指定标识符(宏名)代替字符序列(宏体)

如    #define    YES   1
       #define     NO     0
       #define     PI      3.1415926
       #define     OUT     printf(“Hello,World”);

如              if(x==YES)           printf(“correct!\n”);
                 else if (x==NO)     printf(“error!\n”);
展开后:   if(x==1)           printf(“correct!\n”);
                 else if (x==0)     printf(“error!\n”);

例  #define   WIDTH   80
      #define   LENGTH   WIDTH+40
      var=LENGTH*2;
宏展开:var= 80+40 *2;


宏定义的规则
宏名一般习惯用大写字母表示,以便与变量名相区别

宏定义不是C语句,不必在行末加分号

在进行宏定义时,可以引用已定义的宏名,可以层层替换。

只作字符替换,不分配内存空间。


宏定义的特点

宏名一般习惯用大写字母表示

提高程序的通用性

宏名的有效范围为定义命令之后到本源文件结束

可以用#undef命令终止宏定义的作用域

宏定义只作简单的替换,不作正确性检查



1-2-2 带参数宏定义

一般形式:  #define    宏名(参数表)     宏体

例   #define    S(a,b)    a*b
        ………..
       area=S(3,2);
宏展开:         area=3*2;


带参宏规则

形参用实参换,其它字符保留;

宏名与参数列表之间不能有空格;
宏体及各形参之间应加空格;
注意宏体的括号;


例  #define   POWER(x)      x*x
      x=4;   y=6;
      z=POWER(x+y);
宏展开:z=x+y*x+y;
一般写成:  #define    POWER(x)    ((x)*(x))
宏展开:  z=((x+y)*(x+y));


带参数宏定义的特点
带参宏定义中,宏名和形参表之间不能有空格出现 
例如: #define MAX(a,b) (a>b)?a:b
写为: #define MAX (a,b) (a>b)?a:b 
将被认为是无参宏定义,宏名MAX代表字符串 (a,b)(a>b)?a:b 
在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义 
 在宏定义中的形参是标识符,而宏调用中的实参可以是表达式 

#define SQ(y) (y)*(y)
main()
{
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=SQ(a+1);
printf("sq=%d\n",sq);
}

带参的宏和带参函数很相似,但有本质上的不同



#undef定义指令删除前面定义的宏名字。
表达一般形式为:
#undef macro-name


例子
#define MICRO 1
#undef MICRO


1-3 文件包含

功能:一个源文件可将另一个源文件的内容全部包含进来
一般形式:  #include   “文件名”
                或     #include    <文件名>

处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译

文件包含可嵌套

/*  powers.h  */
#define  sqr(x)     ((x)*(x))
#define  cube(x)   ((x)*(x)*(x))
#define  quad(x)   ((x)*(x)*(x)*(x))

#include <stdio.h>
#include "powers.h"
#define  MAX_POWER 10
void main()
{   int n;
   printf("number\t exp2\t exp3\t exp4\n");
   printf("----\t----\t-----\t------\n");
   for(n=1;n<=MAX_POWER;n++)
     printf("%2d\t %3d\t %4d\t %5d\n",n,sqr(n),cube(n),quad(n));
}


文件包含特点
一个include命令只能指定一个被包含文件


可以用双引号括起来,也可以用尖括号括起来。 


文件包含允许嵌套


被包含文件(file2.h)与其所在的文件(file.c)在预编译之后已成为同一个文件


1-4 条件编译

#if、#else、#elif #endif 

#ifdef和#ifndef 

条件编译指令中最常用的或许是#if,#else,#elif和#endif 
#if的一般形式是:
#if constant-expression
  Statement sequence
#endif
#endif标记#if块的结束 
例子:
       #ifdef COMPUTER_A
     #define INTEGER_SIZE 16
            #else
     # define INTEGER_SIZE 32
            #endif

#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令 
#else既是标记#if块的结束,也标记#else块的开始 
每个#if只能写一个#endif匹配 


#elif指令的意思是“否则,如果” 
语法格式:
#if expression
  Statement sequence
#elif expression1
  Statement sequence
#elif expression2
  。。。。。。
#elif expression
  Statement sequence
#endif 


#ifdef --如果已定义 
#ifdef的一般形式如下:
#ifdef   标识符
     程序段1
#else
     程序段2
#endif
当所指定的标识符已经被#define命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。

#ifdef和#ifndef

#inlucde <stdio.h>
#define T 10
int main(void)
{
         #ifdef t
    Printf(“Hi T\n”);
         #else
    Printf(“Hi anyone\n”);
         #endif
         #ifndef M
    Printf(“M Not Defined\n”);
        #endif
        return 0;
}

操作符#通常称为字符串化的操作符

#include <stdio.h>
#define mkstr(s) #s
int main(void)
{
    Printf(mkstr(I like C)); 
    Return 0;
}

预处理程序把以下的语句:
      Printf(mkstr(I like C));
变成

Printf(“I like C”);


##”可以把两个独立的字符串连接成一个字符串 

#define CONNECT(X, Y) X##Y


void cout1(){printf("mode 1\n");}
void cout2(){printf("mode 2\n");}
void cout3(){printf("mode 3\n");}


int main()
{
CONNECT(cout, 3)();


}

1-5-6 预定义宏

__DATE__  进行预处理的日期(“Mmm dd yyyy”形式的字符串文字)
__FILE__  代表当前源代码文件名的字符串文字
__LINE__ 代表当前源代码中的行号的整数常量
__TIME__ 源文件编译时间,格式微“hh:mm:ss”
__func__ 当前所在函数名 


例子

#include <stdio.h>
#include <stdlib.h>
void why_me();
int main()
{
    printf( "The file is %s.\n", __FILE__ );
    printf( "The date is %s.\n", __DATE__ );
    printf( "The time is %s.\n", __TIME__ );
    printf( "This is line %d.\n", __LINE__ );
    printf( "This function is %s.\n", __func__ );
    why_me();
    return 0;
}

void why_me()
{
    printf( "This function is %s\n", __func__ );
    printf( "The file is %s.\n", __FILE__ );
    printf( "This is line %d.\n", __LINE__ );
}


0 0