请考虑以下代码:
#include <iostream>
#include <math.h>
double log(double) { return 42; }
int main() {
std::cout << log(1) << std::endl;
}
构建调试版本时,所有使用的编译器(msvc,gcc,clang)都打印42
。
但是当我在发布模式下尝试构建(并运行)时,我得到了:
error C2169: 'log' : intrinsic function, cannot be defined
; 42
; 0
。为什么同一编译器的发布/调试结果不同?
为什么在发布模式下为不同的编译器获得了不同的结果?
答案 0 :(得分:5)
您正在定义一个已在<math.h>
中使用外部链接声明的函数。
C11标准,§7.12.6.7:
#include <math.h> double log(double x);
§7.1.2:
库函数的任何声明都应具有外部链接。
[extern.names] / 3:
使用外部链接声明的标准C库中的每个名称 保留给实现用作extern“C”的名称 链接,在名称空间
std
和全局名称空间中。
根据[reserved.names] / 2,行为未定义;因此,实现可以按照自己的意愿行事,包括发布无意义的错误消息。
答案 1 :(得分:2)
所以根据标准(17.6.1.2.4):
但是,在C ++标准库中,声明(除了在C中定义为宏的名称除外)都在命名空间std的命名空间范围(3.3.6)内。未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式using-declarations(7.3.3)注入到命名空间std中。
未指明log()
中的math.h
(真cmath
)是否在名称空间std
中。如果是(就像libstdc ++ for gcc那样),那么调用log(1)
非常简单地调用你的函数,因为另一个名为std::log()
。但是对于clang来说,显然它把它放在全局命名空间中。因为有一个
template <typename T> double log(T x);
因为你传递了一个int,所以你会更喜欢这个,所以在clang上它会调用那个。 (我现在无法检查,因为我无法访问coliru并且没有安装clang,但这是最佳猜测。)