1. 宏定义的次序
宏定义对定义位置之后的代码段有效。
#include <stdio.h>
int main(){
char X = 'a';
char c1 = X;
printf("%c\n",c1);
#define X 4
int i = X;
printf("%d\n",i);
}
输出结果为a和4.
看如下代码:
#include <stdio.h>
#define TABLESIZE BUFSIZE
#define BUFSIZE 1024
int main(){
printf("%d\n",TABLESIZE);
}
输出是1024
在定义TABLESIZE之前,BUFSIZE并没有定义,程序却能正确输出,原因在于,宏在使用的过程中才被解析,因此,在printf调用时,需要解析TABLESIZE,发现里面有另外一个宏BUFSIZE,继续解析BUFSIZE,最终输出1024.
2. 复杂宏函数定义方式
下面的例子通不过编译:
#include <stdio.h>
#define SAYHELLO(){printf("%s\n","hello");}
int main(){
int isSayHello = 0;
if(isSayHello)
SAYHELLO();
else
printf("%s\n","good bye");
}
定义了宏函数SAYHELLO,并且在内部输出hello,在主函数中定义isSayHello变量,如果不为0就执行宏SAYHELLO,如果为0,就输出good bye。上面的代码是通不过编译的,编译器给出error: 'else' without a previous 'if'的错误,意思是说,else前面没有if语句。原因在于if语句后面是{printf("%s\n","hello");}语句,紧接着后面又跟了个;,表示空语句。
正确的书写方式为:
if(isSayHello)
SAYHELLO()
else
printf("%s\n","good bye");
在c语言代码中,有一行调用后面竟然没有;,很多人看代码的时候都会认为是个异常,这种代码方式的确不美观,可以采用do … while的形式解决问题,如下:
#define SAYHELLO() do{printf("%s\n","hello");}while(0)
此时代码中就可以写成
if(isSayHello)
SAYHELLO();
else
printf("%s\n","good bye");
更符合c语言的规则。
使用do…while(0)的形式主要是处理很复杂的代码片段,如果不复杂,直接放到后面或者加个()也是ok的。
3. #号在宏中的作用
#号在宏中可以将参数做字符串输出。
#include <stdio.h>
#define WARN_IF(EXP)\
do{if(EXP)\
printf("%s\n",#EXP);}\
while(0)
int main()
{
int x = 0;
WARN_IF(x==0);
}
输出结果:x==0
需要注意的是,如果参数是宏,那么只能输出宏的名字,而不是值。
#include <stdio.h>
#define STR(s) #s
#define SIZE 1024
int main()
{
int x = 0;
printf("%s\n",STR(SIZE));
}
输出结果为:SIZE
如果需要输出宏的值,可以使用如下形式:
#include <stdio.h>
#define STRX(S) STR(S)
#define STR(s) #s
#define SIZE 1024
int main()
{
int x = 0;
printf("%s\n",STRX(SIZE));
}
##在宏里面表示连接的意思,即使传入的参数是数字,也会被连接在一起。
#include <stdio.h>
#define COMPLEX(X) (X##X)
int main()
{
int x = 0;
printf("%d\n",COMPLEX(10));
}
输出1010
4. 可变参数的宏
#include <stdio.h>
#define PRINT(...) fprintf(stderr,__VA_ARGS__)
int main()
{
int x = 0;
PRINT("%s:%d\n","x",x);
}
输出:x:0
或者将宏写成
#define PRINT(args…) fprintf(stderr,args)
5 宏参数是函数
如果宏参数是函数的时候,你最好写成这个样子:
#define MIN(X,Y) \
({typeof(X) x_ = (X);\
typeof(Y) y_ = (Y);\
(x_<y_)?x_:y_;})
原因是,如果你写成这样:
#include <stdio.h>
#define MIN(X,Y) ((X)<(Y)?(X):(Y))
int getx(){
static int x = 0;
return x++;
}
int main()
{
int y = 1;
MIN(getx(),y);
printf("%d",getx());
}
结果是2
调用一次宏,会调用两次函数。
参考:http://gcc.gnu.org/onlinedocs/cpp/Macros.html