[英]Printing the address of function… declaration?
Consider the following MCVE: 考虑以下MCVE:
#include <iostream>
int main()
{
void foo(int);
std::cout << foo << std::endl;
return 0;
}
Here I intentionally try to print a pointer to a function in a wrong way so that the operator<< overload which accepts bool
is chosen. 在这里,我故意尝试以错误的方式打印指向函数的指针,以便选择接受
bool
的operator << overload 。
basic_ostream& operator<<( bool value );
The thing that puzzles me is that both gcc 7.2 and clang 5.0 produce a warning, but compile and link the program. 令我困惑的是, gcc 7.2和clang 5.0都会产生警告,但编译并链接程序。
In the same time, Visual Studio 15.5.6 doesn't link this example. 同时, Visual Studio 15.5.6没有链接此示例。
Personally, I expected, that this code won't link at all despite the compiler used as foo
seems to be ODR-used . 我个人预计,尽管编译器使用
foo
似乎是ODR使用的,但这个代码根本不会链接。
Could anybody explain why gcc and clang are able to link the program? 有人可以解释为什么gcc和clang能够链接该程序吗?
It is an ODR violation. 这是ODR违规。 But according to [basic.def.odr]/10 , emphasis mine:
但根据[basic.def.odr] / 10 ,强调我的:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement;
每个程序应该只包含每个非内联函数或变量的一个定义,该函数或变量在废弃语句之外的程序中使用。 no diagnostic required .
无需诊断 。 The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]).
该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(参见[class.ctor],[class.dtor]和[class.copy] ])。 An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.
内联函数或变量应在每个翻译单元中定义,在翻译单元中,在废弃的语句之外使用它。
And we must recall that compilers are free to assume you don't write code that exhibits undefined behavior or is otherwise ill-formed in ways they don't need to diagnose. 我们必须记住,编译器可以自由地假设您不会编写表现出未定义行为的代码,或者以其他方式不需要诊断的格式错误。 Because each function must have an address that isn't null, the
bool
overload can just be called with true
, since that's what the conversion must yield in a valid program . 因为每个函数必须具有非null的地址,所以可以使用
true
调用bool
重载,因为这是转换必须在有效程序中产生的 。
We can see GCC 7.3 doing just that. 我们可以看到GCC 7.3正是这样做的。 It passes 1 for what is meant to be the result of the conversion, even at
-O0
. 它通过1表示转换的结果,即使在
-O0
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.