预处理器c++的工作

Working of pre-processor C++

本文关键字:工作 c++ 处理器 预处理      更新时间:2023-10-16
#define NAME VALUE 

我知道无论何时编译器看到这个,它都会用VALUE替换NAME。但是我对预处理指令的工作感到困惑,例如:

#define CONFIG_VAR(name, type, value) 

这并没有告诉编译器替换任何东西,但是我可以看到像

这样的语句
CONFIG_VAR(rank, int, 100)

可以成功编译。这是如何工作的呢?

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

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

#define CONFIG_VAR(name, type, value) add_config_var<type>(name, value)
它会突然做一些有用的事情。所以,我猜宏是一个占位符,用于在该部分程序中尚未实现或不可用的功能。

当你说:

#define FOO BAR
预处理器所做的是在每次看到文本 FOO之后替换为文本BAR,这是一个宏定义。这个过程称为宏扩展。这主要用于定义常量,如:
#define N 128
#define MASK (~(1 << 4))

可以被(ab)用来做非常奇怪的事情,因为它不知道表达式、语句或任何东西。所以:

#define CONST (1 + 3 << (x))

实际上是可以的,并且每次看到它都会扩展为(1 + 3 << (x))每次使用x的当前值。还有像这样的垃圾:

#define START 5 * (1 +
#define END   + 5)

后接START 2 + 3 + 4 END可预见地得到5 * (1 + 2 + 3 + 4 + 5) '

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

#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++中的模板)。有太多的代码使用这种预处理器的用法(有太多的手指这样写),所以几乎不可能摆脱它。作为一个经验法则,学习使用宏读取代码,同时学习不使用宏编写代码(在合理的情况下,有时它们非常方便…)。

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

#ifdef DEBUG
#define dprintf(...) printf(...)
#else
#define dprintf(...)    // This will remove dprintf lines
#endif

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

如果这确实是整个宏定义,那么它只需定义这个类函数的宏来展开为nothing(一个空字符串)。例如,在源代码中,

CONFIG_VAR(rank, int, 100);

将被转换成

;

在这种情况下,预处理程序只是删除这些字符串(不替换)。足够广泛使用的技术

这里有一个很重要的例子(实际上只有一种可能的用法):

#if DEBUG_ON
#define LOG(level, string) SomeLogger(level, string)
#else
#define LOG(level, string)
#endif

也许你应该更熟悉C预处理器。

有一些类似的技术(X宏),它构建代码来处理基于定义动作的重复列表。