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