C++ 关于语言链接,GCC和clang是否显示了与VisualStudio相同的结果?

C++ 关于语言链接,GCC和clang是否显示了与VisualStudio相同的结果?,c++,language-lawyer,linkage,C++,Language Lawyer,Linkage,: 链接规格嵌套。当链接规范嵌套时 最里面的一个决定了语言的联系。连杆机构规范 不建立范围。联动装置规范仅适用于 在命名空间范围中。在悬挂机构规范中,指定的 语言链接适用于所有函数的函数类型 声明符、带有外部链接的函数名和变量 在链接规范中声明了具有外部链接的名称。 [ 例如: extern "C" // the name f1 and its function type have C language linkage; void f1(void(*

:

链接规格嵌套。当链接规范嵌套时 最里面的一个决定了语言的联系。连杆机构规范 不建立范围。联动装置规范仅适用于 在命名空间范围中。在悬挂机构规范中,指定的 语言链接适用于所有函数的函数类型 声明符、带有外部链接的函数名和变量 在链接规范中声明了具有外部链接的名称。 [ 例如:

extern "C"                      // the name f1 and its function type have C language linkage;
  void f1(void(*pf)(int));      // pf is a pointer to a C function

- 结束示例 ]

请注意,传递给下面函数
c_f()
的指针
&foo
不是指向c函数的指针。此代码在VS2017中正常编译和链接。但根据[dcl.link]/4,它不应该这样做

文件
main.cpp

#include <stdio.h>
extern "C"                          // the name c_f and its function type have C language linkage;
void c_f(void(*pf)(int));           // pf is a pointer to a C function

void foo(int i) {
    printf("%d\n", i);
}

extern "C" void c_foo(int);

int main() {
    c_foo(1);       // Calls c_foo(int) defined in other.c
    c_f(&foo);      // Calls c_f(void(*)(int)) defined in other.c, but &foo is not a pointer to a C function !! 
}
我很想知道clang和GCC是否符合该标准,但我无法在web编译器中验证这一点

编辑

我突然意识到,在上面提到的问题上,我真的不需要两个文件来验证clang和GCC是否符合标准<代码> >代码> Meal.CPP<代码>提供C++函数的地址,C++编译器在编译该文件时必须要抱怨一次。但是,这既不发生也不发生。那么,我也可以说,CLAN和GCC在这方面也都是错误的。


1) 如果我们假设需要进行诊断

您的代码根据和显示未定义的行为(重点是我的):

[dcl.link]/1:

所有函数类型、具有外部链接的函数名和具有外部链接的变量名都具有语言链接[ 注意:与具有语言链接的实体相关联的某些属性是特定于每个实现的,此处不进行描述。例如,特定语言链接可能与表示具有外部链接的对象和函数名称的特定形式相关联,或者与特定调用约定相关联,等等- 尾注 ] 所有函数类型、函数名和变量名的默认语言链接是C++语言链接。<强>两个具有不同语言链接的函数类型是不同类型,即使它们在其他方面相同:>/P> [expr.call]/1:

函数调用是一个后缀表达式,后跟括号,括号中可能包含空的、逗号分隔的初始值设定项子句列表,构成函数的参数。后缀表达式应具有函数类型或函数指针类型。对于非成员函数或静态成员函数的调用,后缀表达式ion应为引用函数的左值(在这种情况下,函数到指针的标准转换在后缀表达式上被抑制),或应具有函数指针类型。通过函数类型不同于被调用函数定义的函数类型的表达式调用函数会导致未定义的行为([dcl.link])。对于非静态成员函数的调用,后缀表达式应为隐式([class.mfct.non-static],[class.static])或显式类成员访问,其id表达式是函数成员名称,或指向选择函数成员的成员表达式的指针;该调用是作为对象表达式引用的类对象的成员进行的。对于隐式类成员访问,隐式对象是此函数所指向的对象[ 注意:形式为f()的成员函数调用被解释为(*this).f()(请参见[class.mfct.non-static])- 尾注 ] 如果使用函数或成员函数名,则可以重载该名称,在这种情况下,应根据[over.match]中的规则选择适当的函数。如果所选函数是非虚拟函数,或者如果类成员访问表达式中的id表达式是限定id,则调用该函数。否则,将调用其在对象表达式的动态类型中的最终重写器;此类调用称为虚拟函数调用[ 注意:动态类型是由对象表达式的当前值引用的对象类型。[class.cdtor]描述了当对象表达式引用正在构造或销毁的对象时虚拟函数调用的行为- 尾注 ]


为什么你不能用godbolt.org之类的东西来检查一下呢?@JesperJuhl我该如何在这个网站上插入第二个要编译的文件呢?嗯,很好的一点:-/我想你可以一直安装clang和gcc,然后在本地试用:-)@JesperJuhl请看上面的编辑
#include <stdio.h>

void c_f(void(*pf)(int)){
    pf(2);
}

void c_foo(int i) {
    printf("%d\n", i);
}