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