在 f2c.h 文件中定义 min() max() 宏时出错
Posted
技术标签:
【中文标题】在 f2c.h 文件中定义 min() max() 宏时出错【英文标题】:Error defining min() max() macro in f2c.h file 【发布时间】:2018-08-01 20:45:13 【问题描述】:编译使用 f2c.h 头文件的基于 C++ 的项目,在头文件中是 min 和 max 的宏定义,如下所示...
#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) >= (b) ? (a) : (b))
#endif
当我使用 Microsoft Visual Studio 在 Windows 上编译和运行时,这段代码没有问题。现在我正在尝试使用 g++ 编译器在 LINUX 上编译和运行,我收到以下错误消息...
In file included from tsdriver.cpp:68:0:
/usr/include/c++/6/bits/fstream.tcc: In member function ‘virtual
std::basic_filebuf<_CharT, _Traits>::int_type std::basic_filebuf<_CharT,
_Traits>::underflow()’:
f2c.h:155:18: error: expected unqualified-id before ‘(’ token
#define min(a,b) ((a) <= (b) ? (a) : (b))
现在,它只给我 min 宏的错误消息,但我相信这是由于编译器错误导致编译必须终止。
我做了一些测试,发现可以从一个小的 test.cpp 程序调用 min/max 而没有任何额外的包含,所以最初认为错误来自重新定义,但这不重要,因为 #ifndef 会防止这种情况发生?
我不确定如何解决这个问题,我仍在适应 LINUX 开发环境。任何帮助表示赞赏。
谢谢。
【问题讨论】:
将using namespace std;
与代码一起应用到任何位置。
还要确保 #include "f2c.h"
在所有标准标头之后完成。
πάντα ῥεῖ,您是指从 f2c.h 头文件中删除命名空间 std 吗?
NathanOliver 就是这样,有趣的是这不是 VS 的问题。
@JeremyStalmer 其他人提到它,但在 C++ 中的 <algorithm>
标头中已经有一个 std::min 和 std::max
函数。您的宏版本干扰了这些声明。最好的办法是删除 C 宏,只使用 std::min
和 std::max
。此外,这也是为什么 using namespace std;
很危险的原因——使用无处不在的 C 宏 min
和 max
,以及 std::min
和 std::max
函数。
【参考方案1】:
恭喜,您刚刚学会了为什么macros are evil 的艰难方法;) 宏的问题在于,它们实际上只不过是一种自动文本替换机制,它在“实际”编译器看到它之前更改源代码.他们确实不尊重一般的命名空间或范围之类的东西,因为它们在这些概念甚至还不存在的水平上运作。 C++ 从 C 继承了宏。但是,使用 constexpr
、inline
和模板,C++ 有更好的方法来解决您通常在 C 中使用宏来解决的大多数问题。虽然可能有一些合法的用例C++ 中的宏,如果可能,通常最好避免使用宏。
那么当你用 g++ 编译你的代码时发生了什么?嗯,fstream.tcc 的第 396 行,它是您正在使用的标准库实现的一部分,如下所示:
__ilen = std::min(__avail, __buflen);
很可能,您包含了间接包含 fstream.tcc 的标准库的某些部分。很可能,您在宏定义中包含了标题
#define max(a,b) ((a) >= (b) ? (a) : (b))
在包含该标准标题之前。这意味着当编译器通过 fstream.tcc 时,您已将 max
定义为类似函数的宏。因此,编译器将相应地替换所有匹配 max
(
... ,
... )
的标记序列。这意味着而不是
__ilen = std::min(__avail, __buflen);
你的标准标题突然变成:
__ilen = std::((__avail) >= (__buflen) ? (__avail) : (__buflen))(__avail, __buflen);
// ^--- note this part
这也解释了奇怪的错误信息:
'(' 标记之前的预期 unqualified-id
std::(
是语法错误。编译器期望在::
之后有另一个标识符。原来有一个。但是宏用垃圾替换了那个标识符。因为所有宏所做的只是替换标记而不考虑语法上下文。而且由于宏只是默默地为您重写代码,因此您永远无法看到“实际”编译器看到的代码。当出现问题时,您所看到的只是重写代码产生的错误消息。 (除非你告诉你的编译器请转储出预处理的结果,并筛选你得到的文本海洋。)
解决问题的最佳方法:摆脱宏,只使用std::min()
和std::max
。如果这不是那么容易做到的,那么至少应该可以将这些宏转换为内联函数。
【讨论】:
以上是关于在 f2c.h 文件中定义 min() max() 宏时出错的主要内容,如果未能解决你的问题,请参考以下文章
如何为空输入(而不是默认的+Inf和-Inf)指定R中Max,Min的自定义返回值?
在 codeigniter 中验证 max_length、min_length
在 postgresql 中使用 MIN, MAX, (SUM/COUNT) 子查询