编译预处理
#define可以定义宏。宏可以带参数,叫做带参数的宏,其参数叫做宏的参数。
#undef 可以解除宏的定义。
1 /* 2 宏练习 3 */ 4 5 #include <stdio.h> 6 #define NEG( r) r = 0 - r 7 8 main() 9 { 10 int value = 4; 11 NEG(value); 12 printf("value是%d\n", value); 13 }
1 /* 2 宏练习 3 */ 4 #include <stdio.h> 5 #define STR(r) #r 6 #define PTR(r) p_##r 7 main() 8 { 9 printf("STR(3 + 6) 是 %s\n", STR(3 + 6)); //printf("STR(3 + 6) 是 %s\n", "3 + 6"); 10 int value, *PTR(value) = &value; //int value, *p_value = &value; 11 *PTR(value) = 4; 12 printf("*PTR(value) 是 %d\n", *PTR(value)); 13 }
1 /*宏练习 2 带参数的宏 3 4 求两个数字中的较大者*/ 5 6 #include <stdio.h> 7 #define N 2 8 #define MAX(a, b) a > b ? a : b 9 main() 10 { 11 int integers[N] = {0}; 12 13 14 scanf("%d%d",integers, integers + 1 ); 15 printf("integers[0]>integers[1]?integers[0]:integers[1]输出结果%d\n",integers[0]>integers[1]?integers[0]:integers[1] ); 16 printf("#define MAX(a, b) a > b ? a : b\n 计算结果是%d\n", MAX(*integers, *(integers + 1))); 17 18 }
1 /* 2 * 宏练习 3 */ 4 5 #include <stdio.h> 6 7 #define PI 3.1415926//宏PI如果没有在源程序中声明(定义),我们还可以通过gcc的选项-D来定义宏 8 9 #define CIRCLE(r) 2 * PI * r 10 11 int main() 12 { 13 int radius = 0; 14 printf("Please input radius:"); 15 scanf("%d", &radius); 16 printf("Rounder of the circle: %g ", CIRCLE(radius)); 17 }
1 /* 2 宏练习 3 */ 4 5 #define SECPH (60 * 60 * 60)//加上括号,防止不适当的地方出现了计算优先级问题 6 7 #define NEG(n) -n 8 #include <stdio.h> 9 10 main() 11 { 12 13 printf("7200 / SECPH 是 %d\n", 7200 / SECPH); 14 printf("#define NEG(n) 是 %\n", NEG(3)); 15 //printf("#define NEG(n) 是 %\n", NEG(3, 8));//预处理阶段就报错,错误: 宏“NEG”传递了 2 个参数,但只需要 1 个 16 17 printf("#define NEG(n) 是 %\n", NEG(3 + 8)); 18 printf("#define NEG(n) 是 %\n", NEG((3 + 8))); 19 }
对于带参数宏,我们要注意:
/*
定义得不好的带参数宏往往会导致预处理时对宏进行了非预期的替换。
避免宏在预处理时候进行非预期的替换,我们要求:
宏的所有参数在使用的时候要用小括号包括起来,宏的计算结果要用小括号括起来;加上括号,防止不适当的地方出现了计算优先级问题。
不要使用自增自减的计算结果作为宏参数。
*/
#include <stdio.h>
#define SECPH (60 * 60 * 60)
#define NEG(n) 0 - (n)
#define SQUARE(n) (n) * (n)
main()
{
printf("7200 / SECPH 是 %d\n", 7200 / SECPH);
printf("NEG(3) 是 %\n", NEG(3));
printf("NEG(3 + 8) 是 %\n", NEG(3 + 8));
printf("SQUARE(4) 是 %d\n", SQUARE(4));
int value = 4;
printf("SQUARE(++value) 是 %d\n", SQUARE(++value));
}
附:常见编译器的预定义宏练习
1 /* 2 C语言预定义宏练习 3 */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 printf("行号是 %d\n", __LINE__);//实现打印出当前行号 10 printf("文件名是 %s\n", __FILE__); 11 printf("编译日期是 %s\n", __DATE__); 12 printf("编译时间是 %s\n", __TIME__); 13 printf("%sC标准\n", __STDC__ ? "符合" : "不符合");//宏__STDC__的预处理结果将是一个逻辑表达式,如果符合C标准则计算结果为真。 14 15 }
条件编译。使用预处理指令#if...#else...#endif可以实现按条件编译。
defined 宏名 是一个逻辑运算表达式,当 宏名 已经被定义运算结果为真
/* 条件编译 */ #include <stdio.h> //#define ONE //#define TWO int main() { //#ifdef ONE #if defined ONE //#ifndef TWO //#if !defined TWO printf("1\n"); #else printf("2\n"); #endif }
逻辑非! 逻辑与&& 逻辑或||
条件编译预处理指令#ifdef 宏名 比#if defined 宏名 更简洁;#ifndef 宏名 比 #if !defined 宏名 更简洁。