本文结合《C Primer Plus》和网上的资料(c/c++中define用法详解及代码示例_MachineChen的博客-CSDN博客_define在c语言中用法)对C语言中的define做一个总结
每行#define(逻辑行)都由3部分组成。第1部分是#define指令本身。第2部分是选定的缩写,也称为宏。有些宏代表值,这些宏被称为类对象宏;C语言还有类函数宏。宏的名称中不允许有空格,并且只能使用字符、数字和下划线,而且首字符不能是数字。第3部分称为替换列表或替换体。
类对象宏(无参宏), 即宏名之后不带参数,只是简单的文本替换
其定义的一般形式为:
#define 标识符 字符串
类函数宏(带参数的宏)
定义常量
//定义常量
#define MAX_VALUE 100 //定义整型变量MAX_VALUE值为100
#define USER_NAME "huge" //定义字符串变量USER_NAME值为"huge"
#define PI 3.1415926 //定义浮点数变量PI值为3.1415926
在#define中使用参数
在#define中使用参数可以创建外形和作用与函数类似的类函数宏。
定义简单函数
//定义简单函数
#define MAX(a,b) (a>b)?a:b //取两个数最大值
#define MIN(a,b) (a<b)?a:b //取两个数最小值
定义多行函数
需要在每行换行时加一个\
//定义复杂多行的函数
#define MACRO(arg1, arg2) do { \
\
stmt1; \
stmt2; \
\
} while(0)
关键是要在每一个换行的时候加上一个 "\ "
宏定义中的特殊字符
(1) #
在字符串中包含宏参数,#作一个预处理运算运算符,可以把语言符号转化为字符串。如果x是一个宏参量,#x可以把参数名转化成相应的字符串。该过程称为字符串化。例如:
#incldue <stdio.h>
#define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x)) //#x用x替换
int main(void)
{
int y =4;
PSQR(y);
//输出:the square of y is 16.
PSQR(2+4);
//输出:the square of 2+4 is 36.
return 0;
}
(2)##
##运算符可以用于类函数宏和类对象宏的替换部分。这两个运算符把两个语言符号组合成单个语言符号。
#include <stdio.h>
#define XNAME(n) x##n //x和n拼接成了一个正题
#define PXN(n) printf("x"#n" = %d\n",x##n)
int main(void)
{
int XNAME(1)=12;//int x1=12;
PXN(1);//printf("x1 = %d\n", x1);
//输出:x1=12
return 0;
}
(3)可变参数宏 …和__VA_ARGS__
在宏定义参数列表的最后一个参数为省略号,这样预定义宏__VA_ARGS__就可以被用在替换部分,替换省略号所代表的字符串。
#define PR(...) printf(__VA_ARGS__)
int main()
{
int wt=1,sp=2;
PR("hello\n");
//输出:hello
PR("weight = %d, shipping = %d",wt,sp);
//输出:weight = 1, shipping = 2
return 0;
}
省略号只能代替最后面的宏参数。
#define W(x,…,y)错误!
但是支持#define W(x, …),此时传入的参数个数必须能够匹配。
宏定义中的条件编译
一般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。
#ifdef WINDOWS
......
(#else)
......
#endif
#ifdef LINUX
......
(#else)
......
#endif
取消宏
//定义宏
#define [MacroName] [MacroValue]
//取消宏
#undef [MacroName]
防止重复包含头文件
由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,可能会出现重复定义的问题。可以通过条件编译来避免重复包含
#ifndef __headerfileXXX__
#define __headerfileXXX__
…
文件内容
…
#endif