使用预处理器C ++

时间:2013-04-17 15:59:02

标签: c++ c-preprocessor

#define NAME VALUE 

我知道只要编译器看到这个,它就会用VALUE替换NAME。但我对预处理指令的工作感到困惑,例如:

#define CONFIG_VAR(name, type, value) 

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

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

将成功编译。这是如何运作的 ?

5 个答案:

答案 0 :(得分:2)

在你的例子中,那根本就什么都不做。任何参数,甚至那些看起来应该给出编译错误的参数都被接受,整个宏调用被替换为空字符串。

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

#define CONFIG_VAR(name, type, value) add_config_var<type>(name, value)

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

答案 1 :(得分:2)

当你说:

#define FOO BAR

预处理器所做的是每次更换后,它会通过文本FOO宏定义看到文本 BAR。该过程称为宏扩展。这主要用于定义常量,如:

#define N 128
#define MASK (~(1 << 4))

可以(ab)用于做非常时髦的事情,因为它对表达,陈述或任何东西一无所知。所以:

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

实际上没问题,并且每次看到时都会扩展到(1 + 3 << (x))每次都使用x的当前值。也像gunk一样:

#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 ++中的模板)。有太多的代码使用这种预处理器使用(以及用这种方式编写的手指太多)所以实际上不可能摆脱这种情况。根据经验,学会读取代码使用宏,学习编写代码而不用它们(尽可能合理,有时它们来得非常方便.. )。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

在这种情况下,预处理器只是删除这些字符串(替换为空)。广泛使用的技术。

以下是重要的示例(实际上只有一种可能的用法):

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

可能你应该更熟悉C preprocessor

有些close technique (X macro)构建了基于已定义的操作处理重复列表的代码。

答案 4 :(得分:0)

如果这确实是整个宏定义,那么它只是将这个类似函数的宏定义为扩展为 nothing (空字符串)。例如,在源中,

CONFIG_VAR(rank, int, 100);

将转变为

;