首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >预处理器C++的工作原理

预处理器C++的工作原理
EN

Stack Overflow用户
提问于 2013-04-17 23:59:02
回答 5查看 116关注 0票数 2
代码语言:javascript
复制
#define NAME VALUE 

我知道每当编译器看到这一点时,它就会用值替换NAME。但我对预处理指令的工作原理感到困惑,例如:

代码语言:javascript
复制
#define CONFIG_VAR(name, type, value) 

这并没有告诉编译器替换任何内容,但是我可以看到类似这样的语句

代码语言:javascript
复制
CONFIG_VAR(rank, int, 100)

它将会成功编译。这是如何工作的?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-04-18 00:04:43

在您的示例中,这根本不会做任何事情。任何参数,即使是那些看起来应该给出编译错误的参数,都会被接受,并且整个宏调用空字符串替换。

但是,如果您稍后将该定义替换为以下内容:

代码语言:javascript
复制
#define CONFIG_VAR(name, type, value) add_config_var<type>(name, value)

它会突然做一些有用的事情。所以,我猜想宏是一个占位符,用于程序的该部分中尚未实现或不可用的功能。

票数 2
EN

Stack Overflow用户

发布于 2013-04-18 00:16:58

当你说:

代码语言:javascript
复制
#define FOO BAR

预处理器所做的就是在每次看到文本FOO之后,将其替换为文本BAR,这是一个宏定义。这个过程被称为宏扩展。这主要用于定义常量,例如:

代码语言:javascript
复制
#define N 128
#define MASK (~(1 << 4))

它可以(Ab)用来做非常时髦的事情,因为它对表达式、语句或任何东西一无所知。所以:

代码语言:javascript
复制
#define CONST (1 + 3 << (x))

实际上是OK的,并且每次看到它都会扩展到(1 + 3 << (x)),每次都使用x的当前值。也像这样的粘性:

代码语言:javascript
复制
#define START 5 * (1 +
#define END   + 5)

紧随其后的START 2 + 3 + 4 END可预测地给出5 * (1 + 2 + 3 + 4 +5)`

还可以选择使用参数定义宏,例如:

代码语言:javascript
复制
#define BAD_SQUARE(x)  x * x

如果作为BAD_SQUARE(a)调用,它将扩展为a * a。但是BAD_SQUARE(a + b)扩展到了a + b * a + b,这并不是我们想要的(大概...)。

这来自于C的黑暗时代,今天的C/C++有更安全/更干净的机制来获得相同的结果(在C++中使用const,在C中遗憾的是它定义了一个变量,而不是真正的常量;在C/C++中使用内联函数或在C++中使用模板)。有太多的代码使用了这种预处理器(以及太多以这种方式编写的手指),所以实际上不可能摆脱这种情况。作为一个经验法则,学习使用宏来阅读代码,同时学习在没有宏的情况下编写代码(在合理的情况下,它们有时会非常有用...)。

票数 2
EN

Stack Overflow用户

发布于 2013-04-18 00:10:55

这是一个宏(在C中比在C++中更常见)。根据您提供的定义,预处理器将删除该“函数”的匹配项。一个常见的用例通常用于日志记录:

代码语言:javascript
复制
#ifdef DEBUG
#define dprintf(...) printf(...)
#else
#define dprintf(...)    // This will remove dprintf lines
#endif

在C++中,我认为一般的惯例是使用内联函数,因为它们在性能方面提供了相同的值,但也进行了类型检查。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16064821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档