1.用作符号常量/明示常量时
#define预处理指令和其他预处理指令一样,以#号作为一行的开始。指令可以出现在源文件的任何地方,其定义从出现的地方到该文件的末尾有效。
预处理器指令从#开始,到后面的第一个换行符为止。宏的名字中不允许有空格,而且必须遵循c变量的命名规则:只能使用字母/数字/下划线,而且首字符不能是数字。
注意,宏定义还可以包含其他宏(一些编译器不支持这种嵌套功能)。
例如:
#define TWO 2 //添加注释
#define FOUR TWO*TWO //宏展开为2*2,由于编译器在编译期对所有常量表达式(只包含常量的表达式)求值,所以预处理器不会进 行实际的乘法运算,预处理不做计算,不对表达 式求值,它只进行替换。
#define OW “I am
a student” //反斜杠把该定义延续到下一行
#define HAL ‘Z’ //定义一个字符常量
#define HAL “Z” //定义一个字符串
printf(“TWO: OW”);
打印结果:TWO: OW
一般而言,预处理器发现程序中的宏后,会用宏等价的替换文本进行替换,如果替换的字符文本中还包含宏,则继续替换这些宏。唯一例外的是双引号中的宏。
#define LIMIT 20
const int LTM = 50;
static int data1[LIMIT]; //有效
static int data2[LTM]; //无效
const int LIM2 = 2 * LIMIT; //有效
const int LIM2 = 3 * LTM; //无效
c语言现在支持const关键字,用const可以创建在程序运行时不能改变的变量,宏常量也可用于指定标准数组的大小和const变量的初始值。
在c中,非自动数组的大小应该是整型常量表达式,这说明数组大小必须是整型常量的组合,枚举常量和sizeof表达式。不包括const声明值。但是有的实现可能接受其他形式的常量表达式,例如GCC4.7.3不允许data2的声明,但是Clang4.6允许。
2.在#define中使用参数
在#define中使用参数可以创建外形和作用与函数类似的类函数宏。类函数宏定义的圆括号可以有一个或多个参数。
#define SQUARE(X) X*X
#define PR(X) printf(“The result is %d.n”, X) /宏可以表示任何字符串,甚至可以表示整个c表达式/
int x = 5;
SQUARE(x); //x*x=5*5=25
SQUARE(2); //2*2=4
SQUARE(x+2); //x+2*x+2=17 预期(x+2)*(x+2)
//以上用#define SQUARE(x) (x)*(x)
(100/SQUARE(2)) //100/22=100 预期100/(x+2)
//以上用#define SQUARE(x) (xx)
SQUARE(++x) //++x*++x=42 预期(x+1)*(x+1)
//综合以上可用#define SQUARE(x) ((x)*(x))一次性全部解决
3.用宏参数创建字符串:#运算符
C允许在字符串中包含宏参数。在类函数宏的替换体中,#号作为一个预处理运算符,可以把记号转换成字符串。如果x是一个宏形参,那么#就是转换为字符串x的形参名。这个过程称为字符串化。
#define PSQR(X) printf(“The square of X is %d.n”, ((X)*(X)));
PSQR(8);
The square of X is 64. //此宏的双引号字符串中的X被视为普通文本,而不是一个可被替换的记号。
#define PSQR(x) printf(“The square of " #x " is %d.n”, ((x)*(x)));
PSQR(y);
PSQR(2 + 4);
The square of y is 25. //用"y"替换#x
The square of 2 + 4 is 36. //用"2 + 4"替换#x
4.预处理粘合剂:##运算符
##运算符可用于类函数宏的替换部分,还可用于类对象宏的替换部分。##运算符把两个记号组合成一个记号。
#define XNAME(n) x ## n
#define PRINT_NX(n) printf(“x”#n " = %dn", x ## n);
int XNAME(1) = 14; // 变换成int x1 = 14
PRINT_NX(3); // 变换成printf(“x3 = %dn”, x3);
PRINT_NX宏用#运算符组合字符串,##运算符把记号组合为一个新的标识符。
5.变参宏和__VA_ARGS__
一些函数(如printf())接受数量可变的参数。stdvar.h头文件提供了工具,让用户自定义可变参数的函数。C99/C11也对宏提供了这样的工具。
通过宏参数列表中最后的参数写成省略号(即…)来实现这一功能。这样,预定义宏__VA_ARGS__可用在替换部分中,表明省略号代表什么。
#define PR(…) printf(_VA_ARGS_)
PR(“Howdy”); //宏展开后printf(“Howdy”);
PR(“weight = %d, shipping = $%.2fn”, wt, sp); //宏展开后printf(“weight = %d, shipping = $%.2fn”, wt, sp);
#define PR(X, …) printf("Message " #X ": " _VA_ARGS_)
double x = 48;
double y;
y = sqrt(x);
PR(1, “x = %gn”, x); //宏展开后printf(“Message 1: x= %gn”, x),最终输出Message 1: x = 48
PR(2, “x = %.2f, y = %.4fn”, x, y); //Message 2: x = 48.00, y = 6.9282
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)