简体   繁体   English

打印功能地址...声明?

[英]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. 在这里,我故意尝试以错误的方式打印指向函数的指针,以便选择接受booloperator << 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.2clang 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? 有人可以解释为什么gccclang能够链接该程序吗?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM