预处理器如何处理宏?

时间:2012-01-12 04:32:33

标签: c++ performance macros

我正在阅读Efficient c ++(旧版本),并有一些疑问。 例如,它在这里说:

  

当你做这样的事情时

#define ASPECT_RATIO 1.653
     

编译器可能永远不会看到符号名称ASPECT_RATIO;在源代码编译之前,它可能被预处理器删除。结果,ASPECT_RATIO可能永远不会进入SYMBOLIC_TABLE。如果在涉及常量的编译期间出现错误,则会引起混淆,因为错误消息可能引用1.653而不是ASPECT_RATIO

我不理解这一段。如何将预处理器中的任何东西都删除。可能是什么原因以及它们在现实世界中的可行性。

由于

3 个答案:

答案 0 :(得分:3)

它只是一个全局搜索,并在将文件传递给编译器之前将文件中的“ASPECT_RATIO”替换为“1.653”

这就是宏如此危险的原因。如果您有#define max 123和变量int max = 100,编译器将获得int 123 = 100,您将收到一条令人困惑的错误消息

答案 1 :(得分:3)

  

我不理解倒置引号下的这一段。怎么可以   任何事情都可以删除预处理器,就像那样。可能是什么   它们在现实世界中的原因和可行性。

基本上它描述的是C和C ++预处理器的工作原理。原因是将宏/常量(使用#define指令生成)替换为实际值,而不是一遍又一遍地重复相同的值。在C ++中,使用C风格的宏被认为是一种糟糕的风格,但它们支持C兼容。

预处理器,顾名思义,在实际编译之前运行,并且基本上是通过预处理器指令(以#开头的指令)更改源代码。这还包括用它们的值替换宏,包含#include指令指示的头文件等等。

这用于避免代码重复,幻数,共享接口(头文件)和许多其他有用的东西。

答案 2 :(得分:1)

预处理器将使用实际令牌ASPECT_RATIO替换代码中出现的令牌1.653的所有实例...因此编译器永远不会看到令牌ASPECT_RATIO。在编译代码时,它只能看到由预处理器替换的文字标记1.653

基本上你会遇到这种方法的“问题”是编译器不会将ASPECT_RATIO视为符号,因此在调试器等中,你不能查询值ASPECT_RATIO,如果它是一个变量。它不是具有像static const int那样的内存地址的值(我说“可能”,因为优化编译器可能决定像预处理器一样工作,并优化对显式内存的需求用于存储常量值的地址,而只是替换代码中出现的字面值。在一个更大的函数宏中它也不会有像实际C / C ++函数那样的指令地址,因此你不能在函数宏中设置断点。但是在更一般的意义上,我不确定我会称之为“问题”,除非您打算将宏用作调试符号,和/或在宏内设置调试断点。否则宏正在发挥作用。