cpp语言预编译语句define浅谈

来源:互联网 发布:js点击改变display 编辑:程序博客网 时间:2024/04/28 19:21

最近有人跟我讲,不要用#define,我感觉非常不好,这里来说明一下。

如果有人说不要用#define,那一定是“不要滥用#define”,注意区分……

(全文所有代码请在cmd下运行,或自觉加上system("pause"))

1 简述

一般语法:

#define a b

不带分号。

预编译预编译,它是在编译之前做事的。预编译系统会把在代码中与a完全匹配的字符串找出来,替换为b。

比如,a是123,那么c=a在编译时就变为c=123,但是getchar()就不会有变动,因为以不同类型字符串(例如标识符、运算符、变量名)分割后得到getchar,与a无法完全匹配。

这段表述得有点奇怪,大家能看懂就行……

2 使用

2.1 一般用法

2.1.1 符号常量

define最常见的用处就是定义符号常量。有人说用const不就行了,但首先,const是要占空间的,而define它是预编译,编译之前把所有相关字符串(上面解释了)替换掉。虽然说出题人不至于卡常数卡到一个变量定生死……

当然了,需要注意,有时从时间上来讲,const确实快一些。比如:

const int maxint=(1<<31)-1;#define maxint (1<<31)-1

效果上是一样的,但当大量调用maxint时,前者是调用算好的值,后者是每次调用都重新算一次。所以正确的使用姿势是这样的:

#define maxint 2147483647

这样的话,无论是时间还是空间上,理论上来讲都要有所提升。比后者的提升显而易见,至于前者,空间上是显而易见的,时间上,不要忘了有种东西叫做寻址。虽然差不了多少。但#define的真功夫还不在这里。

话说用const有时会出现值太大无法定义数组的情况,编译器输出很奇怪……如果用#define,错在哪就会很明显。

2.1.2 简单函数

#define做函数与一般函数长得差不多,但应当强调,两者有着本质区别。首先就是#define出来的是不用多占空间的,其次就是它只能写简单函数。

比如:

#define max(a,b) ((a>b)?a:b)
需要注意的是,这里必须加上括号,否则使用起来会出问题,我在用cout做测试(简单测试懒得敲printf……这是有多懒……)时就遇到了问题。加上括号之后就什么毛病都没了。

也可以打多行代码,但仍然是比较简单的:

#define output(a,r,c) for(int i=0;i<r;i++){\for(int j=0;j<c;j++)printf("%c ",a[i][j]);\printf("\n");\}
下面的这个示例程序展示了其应用:

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>#define output(a,r,c) for(int i=0;i<r;i++){\for(int j=0;j<c;j++)printf("%c ",a[i][j]);\printf("\n");\}using namespace std;int main(){char a[10][10]={{'I','X','Z'},{'y','l','U'},{'k','N','O'}};output(a,3,3);return 0;}
这可以大大减少代码量。但坏处显而易见:

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>#define output(a,r,c) for(int i=0;i<r;i++){\for(int j=0;j<c;j++)printf("%c ",a[i][j]);\printf("\n");\}using namespace std;int main(){int a[10][10]={{5,1,12},{14,31,17},{26,7,16}};output(a,3,3);return 0;}
运行一下就会发现出错了,而且错得离谱。因为printf中用的是%c,只能输出字符。当你想写一个自定义库时就会很麻烦。不过尽管如此,#define还是比我们想象的要灵活。(其实上面代码中printf换成cout不就行了……)

2.2 #define的妙用

(像缩短代码这种东西就不用说了……)

2.2.1 调试程序

大家应该知道#ifdef 这条指令。当其后跟随的字符串被通过#define定义过则运行其和#endif之间的代码。例如:

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>#define debuglabelusing namespace std;void debug(){printf("Debug function here:)\n");return ;}int main(){#ifdef debuglabeldebug();#endifreturn 0;}

(可见#define后可以只有一个字符串)

如果注释掉#define语句,运行后就不会看到任何字符串。

#ifndef正好反过来。

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>#define debuglabelusing namespace std;void debug(){printf("Debug function here:)\n");return ;}int main(){#ifndef debuglabeldebug();#endifreturn 0;}
这段代码运行结果与上面那段正相反。程序不会有任何输出,除非注释掉#define。

2.2.2 防止库被重复包含

有时你会在代码里调用很多库,像这样:

syslib.h中:

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>using namespace std;const int a=2147483647;
etclib.h中:

#include"syslib.h"#define max(a,b) ((a>b)?a:b)
etcpro.cpp中:

#include"syslib.h"#include"etclib.h"using namespace std;int main(){return 0;}
然后你就会发现,编译出错了……
原因很简单,有两处包含了syslib.h,a被定义了两次。
解决方案就是#ifndef。把syslib.h改成这样:
<pre name="code" class="cpp">#ifndef included#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctime>using namespace std;const int a=2147483647;#define included#endif
这样就不会出错了。

先介绍这么多,谁想到其他的可以补充下。

0 0
原创粉丝点击