我正在阅读Efficient c ++(旧版本),并有一些疑问。 例如,它在这里说:
当你做这样的事情时
#define ASPECT_RATIO 1.653
编译器可能永远不会看到符号名称ASPECT_RATIO;在源代码编译之前,它可能被预处理器删除。结果,ASPECT_RATIO可能永远不会进入SYMBOLIC_TABLE。如果在涉及常量的编译期间出现错误,则会引起混淆,因为错误消息可能引用1.653而不是ASPECT_RATIO
我不理解这一段。如何将预处理器中的任何东西都删除。可能是什么原因以及它们在现实世界中的可行性。
由于
答案 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 ++函数那样的指令地址,因此你不能在函数宏中设置断点。但是在更一般的意义上,我不确定我会称之为“问题”,除非您打算将宏用作调试符号,和/或在宏内设置调试断点。否则宏正在发挥作用。