我有一个问题:我想使用abs
库的功能complex
。
但是,我遇到错误警告我abs
使用的功能是#define abs(x) (x > 0) ? x : -(x)
.
因此,我认为问题来自我的进口。因为我还包含了 stdio 和 stdlib 库,所以编译器可以使用abs
这些库之一中定义的函数。
所以我的问题是:如何在不删除任何导入的情况下使用abs
库的功能?complex
非常感谢您的回复。
用括号包裹它。
(abs)(whatever);
这将强制编译器使用函数版本,因为宏不再匹配。
类似函数的宏通过匹配标识符后跟左括号来工作(
。由于我们将函数名称本身包装在括号中,因此我们有一个标识符后跟一个右括号)
,它无法匹配宏。括号在语义上是透明的,但它们抑制了宏语法。
IIRC,是splint
C 检查器教给我的。在编写 postscript 解释器时,我创建了很好的短宏来访问堆栈。
#define push(o) (*tos++ = (o))
#define pop() (*--tos)
在它们成为表达式的一部分的棘手部分之前,这很棒tos
。为了避免未定义的行为,我必须创建函数版本并将其用于那些棘手的地方。对于新设计,我完全跳过了宏。
编辑:我有一种挥之不去的感觉,实际上是我在 Coelocanthe 书(Peter Van Der Linden 的Deep C Secrets)中学到了这一点,上述情况是我第一次需要它的地方。IIRC 他的示例涉及putchar
或getchar
通常作为符合 C 实现的函数和宏来实现。
采用#undef
#include "header1.h"
#include "header2.h"
#undef abs // remove abs macro
x = std::abs(y);
虽然上面的几个建议非常好,但我会采取完全不同的角度。几乎可以肯定,类似windows.h
的事情会导致abs()
. 您应该不能在执行复杂数学运算的文件中包含“windows.h”[至少在大多数类型的程序中](我不知道 Windows 中有一个函数complex<T>
作为参数,所以我'很确定你不需要在同一个源文件中同时使用“complex.h”和“windows.h”。这种方法称为“隔离系统依赖项”,这样做是一件非常好的事情。
查看您的代码,找到您实际使用 Windows 函数的位置,然后仅在实际需要它的文件中包含“windows.h”。如果您使用 Visual Studio,您可能会发现“windows.h”作为“stdafx.h”的一部分包含在内,这意味着所有有趣的宏等都包含在所有地方,因为“stdafx .h" 包含在所有源文件中。
和括号解决方案都#undef
可以工作,但我建议有一些更强大的东西,因为这两种解决方案都需要你每次想要调用时都这样做abs
,下次你可能会忘记并导致错误。
你可以做什么:
absolute
等myAbs
...myNameSpace::abs(x)
如果它不能像这里的评论建议的那样工作,我仍然会在我的函数中扭曲调用:
键入 myAbs(类型参数){ 返回(绝对值)(参数);}