15-预处理指令1-宏定义、条件编译、文件包含

1.C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译
2.为了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号
3.预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾。习惯上我们尽可能将预处理指令写在源程序开头,这种情况下,它的作用范围就是整个源程序文件
4.C语言提供的预处理指令主要有:宏定义文件包含条件编译
//    #define Pow (a) ( (a) * (a) )

#include <stdio.h>


// NUM叫做宏名

// 6是用来替换宏名的字符串  

#define NUM 6


#define mul(a, b) ((a)*(b))



void test() {

    // 双引号中的NUM并不会被替换为6  

//对程序中用双引号扩起来的字符串内的字符,不进行宏的替换操作

    char *s = "NUMBER";

    

    

    

    int a[NUM] = {1,2,3,4,5,6};

    

    for (int i = 0; i<NUM; i++) {

        printf("a[%d] = %d\n", i , a[i]);

    }

}


int main(int argc, const char * argv[])

{

    int a = mul(1010) / mul(22);

    // mul(a, b) (a)*(b)

    // (10 * 10) / (2 * 2)

    printf("%d", a);

    return 0;

}



二、带参数的宏定义

1.一般形式

#define 宏名(参数列表) 字符串

 

2.作用

在编译预处理时,将源程序中所有宏名替换成字符串,并且将 字符串中的参数 用 宏名右边参数列表 中的参数替换

1> 宏名和参数列表之间不能有空格,否则空格后面的所有字符串都作为替换的字符串

2> 带参数的宏在展开时,只作简单的字符和参数的替换,不进行任何计算操作。所以在定义宏时,一般用一个小括号括住字符串的参数。

3> 计算结果最好也用括号括起来

下面定义一个宏P(a),作用是返回a的平方:

#include <stdio.h>


#define D(a) 2*a


int main ()

{

    int b = D(3+4);

    

    printf("%d", b);

    return 0;

}

7行将被替换成int b = 2*3+4;,输出结果:

#include <stdio.h>


#define Pow(a) (a) * (a)


int main(int argc, const char * argv[]) {

    int b = Pow(10) / Pow(2);

    

    printf("%d", b);

    return 0;

}

注意第3行,没有用小括号扩住计算结果,只是括住了参数而已。第6行代码被替换为:

int b = (10) * (10) / (2) * (2);

简化之后:int b = 10 * (10 / 2) * 2;


5.与函数的区别

从整个使用过程可以发现,带参数的宏定义,在源程序中出现的形式与函数很像。但是两者是有本质区别的:

1> 宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题

2> 函数调用在程序运行时执行,而宏替换只在编译预处理阶段进行。所以带参数的宏比函数具有更高的执行效率


===========

   条件编译

============

在很多情况下,我们希望程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行),这就是条件编译


#if 条件1

 ...code1...

#elif 条件2

 ...code2...

#else

 ...code3...

#endif



//  main.c

//  条件编译



#include <stdio.h>


#define NUM -1


int main(int argc, const char * argv[])

{

    

#if NUM > 0

    printf("NUM大于0");

#elif NUM == 0

    printf("NUM等于0");

#else

    printf("NUM小于0");

#endif

    

    return 0;

}



===========

   文件包含

============

1.第1种形式#include <文件名>

直接到C语言库函数头文件所在的目录中寻找文件

 

2.第2种形式 #include "文件名"

系统会先在源程序当前目录下寻找,若找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中查找

1.#include指令允许嵌套包含,比如a.h包含b.h,b.h包含c.h,但是不允许递归包含,比如 a.h 包含 b.h,b.h 包含 a.h。

下面的做法是错误


// #include "one.h"

#ifndef _ONE_H_

#define _ONE_H_


void one();


#endif


// #include "two.h"

#ifndef _TWO_H_

#define _TWO_H_


// #include "one.h"

#ifndef _ONE_H_

#define _ONE_H_


void one();


#endif


void two();


#endif








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值