1、#define name(pargament-list) stuff
注意:(1)#define 后面不要加符号,因为在使用宏定义时也会加上符号。
(2)参数列表的左括号必须和name紧邻,如果二者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
如下面代码:10-1=9,9*9=81;但是答案是-1.
#include<stdio.h> #define square(x) x*x int main() { int a = 10; int b = 20; int c = square(a - 1); printf("%d", c); return 0; }
因为square把(10-1)传过去后变成:10-1*10-1=-1;
但是当我们用括号把x括起来时就是我们想要的结果:9*9=81.
还有就是不要省我们的括号,,否则当我们定义宏时会出现意想不到的错误。
如下面代码:
#include<stdio.h> #define add(x,y) (x)+(y) int main() { int a = 1; int b = 2; int c = 3*add(a, b); printf("%d", c); return 0; }
代码答案为5,因此该加括号加括号,保证我们代码的正确性。
2.#和##
(1)#(可以把跟在后面的参数转换成一个字符串)
#include<stdio.h> #define PRINT(n,format) printf(#n" is " format"\n",n); int main() { int a = 1; float b = 2; PRINT(a," %d"); PRINT(b,"%f"); return 0; }
(2)##(可以把位于它两边的符号合成为一个符号)
#include<stdio.h> #define add(x,y) x##y int main() { int ab = 1; printf("%d", add(a, b)); return 0; }
3、宏和函数的比较
(1)、宏相对于函数的优点:
Ⅰ、在运行速度上宏要比函数的运行速度快, 函数需要调用并且返回值这个过程,而宏却不需要。
Ⅱ、在参数的类型定义上,宏没有类型要求,适合于任何能用>号来比较的类型,而函数的参数必须声明特定的类型。
Ⅲ、宏还有一个特殊的地方,宏可以接受类型作为参数。
(2)、函数相对于宏的优点:
Ⅰ、如果一个函数要调用很多次,使用函数可以省略很多不必要的内容,而每次使用宏,宏定义则需要写上好几遍。
Ⅱ、因为宏没有类型要求,所以函数比较于宏来说更加的严谨。
Ⅲ、函数可以调试,而宏不行。因此如果宏出现错误将难以发现。函数还可以递归而宏不可以。
Ⅳ、宏可能会带来运算符优先级的问题,容易导致程序会出错;函数在传参之前,已经将表达式计算好了。
Ⅴ、参数每次进行宏定义时,都会重新求值,多次求值的过程中就会出现错误,而函数却只会在调用的时候求值一次。
4、条件编译
#if 常量表达式
#elif 常量表达式
#else 常量表达式
#endif 常量表达式
#include<stdio.h>
#define i 1
int main() { #if i==1 printf("条件表达式!"); #elif printf("hehe!"); #else printf("haha!"); #endif return 0; }
5、#pragma预处理
(预处理指令有特别多,可翻阅资料)
6、#undef(移除一个宏定义)
如下面代码段:
#include<stdio.h> #define add(a,b) a+b int main() { int a = 1; int b = 2; int c = add(a, b); #undef add int d = add(a, b); return 0; }
编译器会报错: