【C语言】预处理指令—宏定义

感谢:http://www.cnblogs.com/mjios/archive/2013/03/20/2969817.html

一、预处理指令:在编译源文件程序前对源程序进行处理,用#表示该行为编译处理指令。在C语言中加入一些编译预处理指令可以提高编程效率,加快编译速度。

注意:预处理命令不是C语言的一部分,因此每条编译预处理命令不需要以分号来结束。

二、预处理简介

1. C语言在对程序进行编译前,会先对一些特殊的预处理指令作解释(像常见的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理)之后再进行通常的编译;

2. 为了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号;

3. 预处理指令可以出现在程序的任何位置,他的作用范围是从它出现的位置到文件尾。习惯上我们尽可能将预处理指令写在源程序开头,这种情况下,他的作用范围就是整个源程序文件;

4. C语言提供的预处理指令有:文件包含、宏定义、条件编译;

三、宏定义  --  C语言标准允许在程序中用一个标识符来表示一个字符串。标识符就是宏名。

1. 不带参数的宏

    一般形式

    #define 宏名 字符串

    #define  A 100

// 源程序中所有的宏名PI在编译预处理的时候都会被3.14所代替
#define PI 3
float girth(float radius) {
	return 2 * PI *radius;
}

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

	float a = girth(2);<pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif;">        	printf("周长为:%f\n", a);</span>
system("pause");return 0;}

 2. 使用习惯与注意 

    1) 宏名一般用大写字母,以便与变量名区别开来,但用小写也没有语法粗无;

    2) 对程序中用双引号括起来的字符串内的字符不进行宏的替换操作:

#define R 10
int main ()
{
    char *s = "R";     // 这里的R不会替换成10
    return 0;
}
    3) 在编译预处理用字符串替换宏名时,不作语法检查,只是简单的字符串替换。只有在编译的时候才对已经展开的宏名的源程序进行语法检查
#define I 100
int main ()
{
    int i[3] = I;    //  这一行在编译预处理的时候并不会报错,不过在编译的时候就会报编译的错了
    return 0;
}
    4) 宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef命令
#define PI 3.14
/*
.
*/
#undef PI     // 这一行之后就无效了
// 源程序中所有的宏名PI在编译预处理的时候都会被3.14所代替
#define PI 3
float girth(float radius) {
	return 2 * PI *radius;
}
#undef  PI;
// 
float girth2(float radius) {
	// 这里使用宏替换就会出错了
	return 3 * PI *radius;
}
    5) 定义一个宏可以引用已经定义的宏名 (typedef定义结构体等类型也是类似的)    
#define R  3.0
#define PI 3.14
#define L  2*PI*R
#define S  PI*R*R
2. 带参数的宏

    1) 一般形式:

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

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

#include <stdio.h>

#define average(a, b) (a+b) / 2

int main ()
{
    int a = average(10, 4);
    
    printf("平均值:%d", a);
    return 0;      // 结果就是int a = (10 + 4) / 2;
}

    3) 使用注意

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

#define average (a, b) (a+b)/2

int main ()
{
    int a = average(10, 4);
    return 0;
}
可以从上面看出来的是宏名average与 参数列表(a, b)之间有空格,所有int a = 就变成了

int  a = (a, b) (a + b)/2(10, 4);    // (a, b) (a + b)/2是宏体, (10,4)是average后面的

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

         下面定义一个红D(a),作用是返回2的倍数

#include <stdio.h>

#define D(a) 2*a           // 如果定义时候不用小括号括住参数, int b = 2 * 3 + 4;

int main ()
{
    int b = D(3+4);
    
    printf("%d", b);
    return 0;
}
#include <stdio.h>

#define D(a) 2*(a)           // 如果定义时候用小括号括住参数, int b = 2 * (3 + 4);

int main ()
{
    int b = D(3+4);
    
    printf("%d", b);
    return 0;
}
     3. 计算结果最好也用括号括起来
#include <stdio.h>

#define Pow(a) (a) * (a)   // 定义一个宏p(a),作用是返回a的平方;不用小括号括住计算结果    int b = (10) * (10) / (2) * (2);   100

int main(int argc, const char * argv[]) {
    int b = Pow(10) / Pow(2);
    
    printf("%d", b);
    return 0;
}
#include <stdio.h>

#define Pow(a) ((a) * (a))   // 定义一个宏p(a),作用是返回a的平方;用小括号括住计算结果    int b = ((10) * (10)) / ((2) * (2));    25

int main(int argc, const char * argv[]) {
    int b = Pow(10) / Pow(2);
    
    printf("%d", b);
    return 0;
}
3. 与函数的区别

虽然带参数的宏出现的形式与函数很像,不过还是有区别的:

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

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


感谢:http://www.cnblogs.com/mjios/archive/2013/03/20/2969817.html

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值