吾爱程序员:这里有好玩的游戏和软件
当前位置:首页C语言教程 → C 中关于宏和预处理器的有趣事实

C 中关于宏和预处理器的有趣事实

来源:网络 | 更新时间:2022-01-07 23:22:55
在 C 程序中,所有以#开头的行都由预处理器处理,预处理器是由编译器调用的特殊程序。我们的意思是说“#”符号用于比程序中的其他语句更早地处理功能,也就是说,这意味着它在运行时或编译时处理一些代码。在一个非常基本的术语中,预处理器采用一个 C 程序并生成另一个没有任何# 的C 程序。 以下是有关 C 中预处理器的一些有趣事实。  1)当我们使用include 指令时,被包含的头文件(预处理后)的内容被复制到当前文件中。  尖括号<>指示预处理器在保存所有头文件的标准文件夹中查找。双引号指示预处理器查看当前文件夹(当前目录)。  2)当我们对常量使用define 时,预处理器生成一个C 程序,其中搜索定义的常量并将匹配的标记替换为给定的表达式。例如在下面的程序中max被定义为 100。
#include <stdio.h>
#define max 100
int main()
{
printf("max is %d", max);
return 0;
}
输出: 
max is 100
3)宏可以采用类似参数的函数,不检查参数的数据类型。例如,以下宏 INCREMENT(x) 可用于任何数据类型的 x。
#include <stdio.h>
#define INCREMENT(x) ++x
int main()
{
char* ptr = "GeeksQuiz";
int x = 10;
printf("%s ", INCREMENT(ptr));
printf("%d", INCREMENT(x));
return 0;
}
输出: 
eeksQuiz  11
4)在宏扩展之前不评估宏参数。例如,考虑以下程序
#include <stdio.h>
#define MULTIPLY(a, b) a* b
int main()
{
// The macro is expanded as 2 + 3 * 3 + 5, not as 5*8
printf("%d", MULTIPLY(2 + 3, 3 + 5));
return 0;
}
// Output: 16
输出: 
16
可以使用以下程序解决之前的问题 
#include <stdio.h>
// here, instead of writing a*a we write (a)*(b)
#define MULTIPLY(a, b) (a) * (b)
int main()
{
// The macro is expanded as (2 + 3) * (3 + 5), as 5*8
printf("%d", MULTIPLY(2 + 3, 3 + 5));
return 0;
}
// This code is contributed by Santanu
输出: 
40
5)传递给宏的令牌可以使用称为令牌粘贴运算符的运算符##进行连接。
#include <stdio.h>
#define merge(a, b) a##b
int main() 
{ 
printf("%d ", merge(12, 34)); 
}
输出: 
1234
6)传递给宏的标记可以通过在它之前使用# 转换为字符串文字。
#include <stdio.h>
#define get(a) #a
int main()
{
printf("%s", get(52cxydh));
}
输出: 
52cxydh
7)宏可以使用'' 写成多行。最后一行不需要有“”。
#include <stdio.h>
#define PRINT(i, limit) 
while (i < limit) { 
printf("52cxydh"); 
i++; 
}
int main()
{
int i = 0;
PRINT(i, 3);
return 0;
}
输出: 
52cxydh 52cxydh 52cxydh
8)应避免使用带参数的宏,因为它们有时会引起问题。内联函数应该是首选,因为内联函数中有类型检查参数评估。从C99开始,C 语言也支持内联函数。  例如,考虑以下程序。乍一看,输出似乎是 1,但它产生 36 作为输出。
#include <stdio.h>

#define square(x) x* x
int main()
{
// Expanded as 36/6*6
int x = 36 / square(6);
printf("%d", x);
return 0;
}
输出
36
但是我们可以这样写这段代码来得到预期的结果,即 1:
#include <stdio.h>

#define square(x) (x * x)
int main()
{
// Expanded as 36/(6*6)
int x = 36 / square(6);
printf("%d", x);
return 0;
}
输出
1
如果我们使用内联函数,我们会得到预期的输出。此外,可以使用内联函数更正上面第 4 点中给出的程序。
#include <stdio.h>

static inline int square(int x) { return x * x; }
int main()
{
int x = 36 / square(6);
printf("%d", x);
return 0;
}
输出:
1
9)预处理器还支持通常用于条件编译的 if-else 指令。 
int main()
{
#if VERBOSE >= 2
printf("Trace Message");
#endif
}
输出: 
No Output
10)一个头文件可能会被直接或间接包含多次,这会导致重新声明相同变量/函数的问题。为了避免这个问题,使用了诸如definedifdefifndef 之类的指令。  11) C 代码中有一些标准宏可以用来打印程序文件(__FILE__)、编译日期(__DATE__)、编译时间(__TIME__)和行号(__LINE__)
#include <stdio.h>

int main()
{
printf("Current File :%sn", __FILE__);
printf("Current Date :%sn", __DATE__);
printf("Current Time :%sn", __TIME__);
printf("Line Number :%dn", __LINE__);
return 0;
}
输出: 
Current File :/usr/share/IDE_PROGRAMS/C/other/081c548d50135ed88cfa0296159b05ca/081c548d50135ed88cfa0296159b05ca.c
Current Date :Sep  4 2019
Current Time :10:17:43
Line Number :8
12)我们可以使用:#undef MACRO_NAME删除已经定义的宏
#include <stdio.h>
#define LIMIT 100
int main()
{
printf("%d", LIMIT);
// removing defined macro LIMIT
#undef LIMIT
// Next line causes error as LIMIT is not defined
printf("%d", LIMIT);
return 0;
}
以下程序正确执行,因为我们在删除先前定义的宏 LIMIT 后已将 LIMIT 声明为整数变量 
#include <stdio.h>
#define LIMIT 1000
int main()
{
printf("%d", LIMIT);
// removing defined macro LIMIT
#undef LIMIT
// Declare LIMIT as integer again
int LIMIT = 1001;
printf("n%d", LIMIT);
return 0;
}
输出: 
1000
1001
关于宏使用(#undef)的  另一个有趣的事实
#include <stdio.h>
// div function prototype
float div(float, float);
#define div(x, y) x / y

int main()
{
// use of macro div
// Note: %0.2f for taking two decimal value after point
printf("%0.2f", div(10.0, 5.0));
// removing defined macro div
#undef div
// function div is called as macro definition is removed
printf("n%0.2f", div(10.0, 5.0));
return 0;
}

// div function definition
float div(float x, float y) { return y / x; }
输出: 
2.00
0.50
 

最新文章

热点资讯

手游排行榜

CopyRight 2020-2030吾爱程序员

鄂ICP备2021004581号-8

本站资源收集于网络,如有侵权请联系我们:35492删除0109@qq.com