use*_*921 1 c c++ macros preprocessor
我读到#defining和#undefining在一个块里面是代码味道.这是为什么?另外,我在代码中看到(只是一个显示我在实际代码中的内容的示例),这个编译,
if(x == 1000) {
#define MACRO_EXAMPLE 1
} else {
#define MACRO_EXAMPLE 1
}
Run Code Online (Sandbox Code Playgroud)
但这不编译,
if(x == 1000) {
#define MACRO_EXAMPLE 1
} else {
#define MACRO_EXAMPLE 2
}
Run Code Online (Sandbox Code Playgroud)
有错误 warning C4005: 'MACRO_EXAMPLE' : macro redefinition
这是如何预处理的?它是如何工作的?
Nat*_*ica 11
预处理在分析代码之前发生.这意味着if/else被忽略了
if(x == 1000) {
#define MACRO_EXAMPLE 1
} else {
#define MACRO_EXAMPLE 1
}
Run Code Online (Sandbox Code Playgroud)
实际上被视为
#define MACRO_EXAMPLE 1
#define MACRO_EXAMPLE 1
Run Code Online (Sandbox Code Playgroud)
这是可以的,因为你使用相同的值.另一方面
if(x == 1000) {
#define MACRO_EXAMPLE 1
} else {
#define MACRO_EXAMPLE 2
}
Run Code Online (Sandbox Code Playgroud)
变
#define MACRO_EXAMPLE 1
#define MACRO_EXAMPLE 2
Run Code Online (Sandbox Code Playgroud)
并且由于宏的值已经改变,这是一个错误
在处理程序#define的其余部分之前,处理器之类的预处理器在概念上运行.除此之外,这意味着预处理器定义不支持块范围.编译器没有注意到你是否在... 块#define内部完成了.没有机制在... 块结束时自动执行.{}#undef{}
您可以手动执行此操作,如果您愿意:您可以#define在块内部使用,并记住#undef在块的末尾显式执行.但这一切都在你身上:编译器不会检查你的工作,或者如果你弄错了就会发出警告.
因此,这被认为是不好的做法.(我想这就是"代码味道"的意思.)这是不好的做法,因为它容易出错,而且没有好的,自动的方式来捕捉任何错误.
如果您使用预处理器#define,它应该是全局的(因为,基本上,它是全局的,无论您是否想要它).
当然,全球变量也不受欢迎.而这与以下事实有关:现在,预处理器#define几乎都不受欢迎,所有这些都是如此.
像所有风格问题一样,这个问题可能有点争议.当我说手工制作的块范围预处理器定义是"坏风格"时,这并不意味着有一个反对它们的铁定规则.如果你愿意,而且你知道你在做什么,你可以侥幸逃脱; 这里没有人可以阻止你.(如果您在工作中编写代码,并且根据您公司的样式指南,您可能会在代码审查中受到责骂.)
事实上,我每天在工作中使用的代码库都充满了这些"本地范围"的预处理器定义,因为我的一些前辈认为它们很漂亮.我不喜欢他们,但他们确实工作,他们没有造成问题,所以我们没有开始根除他们的运动.
预处理程序指令无论如何都不会阻止范围,无论如何它们都会在编译时产生影响.你的代码示例
if(x == 1000) {
#define MACRO_EXAMPLE 1
} else {
#define MACRO_EXAMPLE 2
}
Run Code Online (Sandbox Code Playgroud)
是100%相当于写作
#define MACRO_EXAMPLE 1
#define MACRO_EXAMPLE 2
if(x == 1000) {
} else {
}
Run Code Online (Sandbox Code Playgroud)
(可能除了调试信息中的行号).现在应该更明显的是为什么这是一个错误.这也是为什么在块内部定义代码气味的原因 - 它们具有文件范围效果,无论如何.
(我依旧记得一个仅在C++中改变它的提议,但我认为它没有去过任何地方.)
这是很好的风格来定义,只有一个顶层结构具有使用结构之前,权利的任何业务的宏,并再次取消定义它随即.你会看到这个用X-macro,例如:
#define X(a, b, c) b,
const int b_tbl[] = {
#include "tbl.inc"
};
#undef X
Run Code Online (Sandbox Code Playgroud)
但请注意#define和#undef 不在定义之内b_tbl,因此它们仍然作为文件范围读取给人类.