简体   繁体   English

预处理器C ++的工作

[英]Working of pre-processor C++

#define NAME VALUE 

I know whenever the compiler see this, it would replace NAME with VALUE. 我知道,只要编译器看到此内容,它将使用VALUE替换NAME。 But I'm confused about the working of pre-processing directives such as : 但是我对预处理指令的工作感到困惑,例如:

#define CONFIG_VAR(name, type, value) 

This does not tell the compiler to replace anything , but I could see statements like 这不会告诉编译器替换任何东西,但是我可以看到类似的语句

CONFIG_VAR(rank, int, 100)

which would compile successfully. 可以成功编译。 How does this work ? 这是如何运作的 ?

In your example, that would simply do nothing at all. 在您的示例中,这根本不起作用。 Any arguments, even those that seem like they should give compilation errors, are accepted and the whole macro call is replaced with an empty string. 接受所有参数,即使那些看起来应该引起编译错误的参数,整个宏调用也将替换为空字符串。

If, however, you later replace the definition with something like: 但是,如果您以后用以下内容替换该定义:

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

it would suddenly do something useful. 它会突然做一些有用的事情。 So, I'd guess that macro is a placeholder for functionality which is not (yet) implemented or not available in that part of the program. 因此,我猜想宏是该功能的占位符,而该功能尚未(尚未)实现或在程序的该部分中不可用。

When you say: 当你说:

#define FOO BAR

what the preprocessor does is to replace each time after this it sees the text FOO by the text BAR , a macro definition . 预处理器所做的事情是每次在它看到文本 FOO用文本BAR宏定义)替换。 The process is called macro expansion . 该过程称为宏扩展 This is mostly used to define constants, like: 这主要用于定义常量,例如:

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

It can be (ab)used to do very funky stuff, as it knows nothing of expressions, statements, or anything. 可能被用来做一些非常时髦的事情,因为它对表达式,语句等一无所知。 So: 所以:

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

is actually OK, and will expand to (1 + 3 << (x)) each time it is seen, using the current value of x each time . 实际上是可以的,并且每次使用x的当前值,每次看到都会扩展为(1 + 3 << (x)) Also gunk like: 也像这样:

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

followed by START 2 + 3 + 4 END predictably gives 5 * (1 + 2 + 3 + 4 + 5)` 随后加上START 2 + 3 + 4 END可预测得到5 * (1 + 2 + 3 + 4 + 5)`

There is also the option of defining macros with parameters , like: 还可以选择使用参数定义 ,例如:

#define BAD_SQUARE(x)  x * x

which, if called as BAD_SQUARE(a) will expand to a * a . 如果称为BAD_SQUARE(a)它将扩展为a * a But BAD_SQUARE(a + b) expands to a + b * a + b , which isn't what was intended (presumably...). 但是BAD_SQUARE(a + b)扩展为a + b * a + b ,这不是预期的(大概是……)。

This comes from the dark ages of C, today's C/C++ have safer/cleaner mechanisms to get the same result (use const in C++, in C it sadly defines a variable, not a real constant; use inline functions in C/C++ or templates in C++). 这来自C的黑暗时代,当今的C / C ++具有更安全/更清洁的机制来获得相同的结果(在C ++中使用const ,可悲的是,在C中它定义了一个变量,而不是一个真正的常量;在C / C ++中使用内联函数或C ++中的模板)。 There is too much code out there that uses this preprocessor usage (and too many fingers who write this way) so it is practically impossible to get rid of this. 那里有太多的代码使用这种预处理器用法(并且有太多的手指以这种方式编写),因此几乎不可能摆脱这一点。 As a rule of thumb, learn to read code using macros, whiel learning to write code without them (as far as reasonable, there are times when they come mighty handy...). 根据经验,学会使用宏读取代码,学会不使用宏来编写代码(在合理的情况下,有时它们变得非常有用……)。

This is a macro (more common in C than in C++). 这是一个宏(在C中比在C ++中更常见)。 According to the definition you provided, the preprocessor will remove occurrences of that "function". 根据您提供的定义,预处理器将删除该“功能”的出现。 A common use-case is usually for logging: 常见的用例通常是用于记录日志:

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

In C++, I believe the general convention is to use inline functions as they provide the same value performance-wise, but are also type checked. 在C ++中,我相信一般约定是使用内联函数,因为它们在性能方面提供相同的值,但也要进行类型检查。

In this case pre-processor simply removes such strings (replaces with nothing). 在这种情况下,预处理器仅删除此类字符串(不替换任何内容)。 Widely enough used technique. 广泛使用的技术。

Here is example where it is important (actually only one of possible usages): 这是重要的示例(实际上只是一种可能的用法):

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

Probably you should get more familiar with C preprocessor . 也许您应该更熟悉C预处理程序

There is somewhat close technique (X macro) which builds code which handles repeating lists based on defined actions. 有某种紧密的技术(X宏)可以构建基于定义的动作来处理重复列表的代码。

If this really is the entire macro definition, then it simply defines this function-like macro to expand to nothing (an empty string). 如果这真的是整个宏定义,然后将其简单地定义这个函数宏扩大到什么 (空字符串)。 For example, in the source, 例如,在源代码中,

CONFIG_VAR(rank, int, 100);

will be transformed into 将转化为

;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM