"外部"C""是函数类型的一部分吗?
Is `extern "C"` a part of the type of a function?
除了链接相关的内容外,我在标准中没有看到任何注释。
虽然标准没有说明调用约定,但在现实世界中,C和C++之间的调用约定可能不同,所以我预计C函数和C++函数的类型不同。但似乎并非如此,尤其是在海湾合作委员会。
#include <type_traits>
extern "C" {
int c_func(int);
}
int cpp_func(int);
static_assert(!std::is_same<decltype(c_func), decltype(cpp_func)>::value,
"It should not be the same type");
CCD_ 1失败,因为GCC认为这些函数具有相同的类型。
extern "C"
是函数类型的一部分吗- 如何检查函数是否使用C调用约定或C++调用约定
该标准清楚地表明,语言链接实际上是函数类型本身的属性:
所有函数类型、具有外部链接的函数名和具有外部链接功能的变量名都有一个语言链接
如果这还不够清楚,有一个注释(强调我的)可以使预期含义明确:
[注意:因为语言链接是函数类型的一部分,所以在通过指向C的指针进行间接寻址时函数,生成的左值所指的函数被认为是C函数。——尾注]
此外,
两种不同语言的函数类型链接是不同的类型,即使它们在其他方面是相同的。
所以你的第一个问题的答案是:
-
是,
extern "C"
是函数类型的一部分
然而,大多数编译器无法区分C和C++语言链接的函数类型。例如,这是GCC中一个长期存在的错误(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316;参见重复项列表)。我没有仔细阅读整个线程,但如果GCC开始强制执行它们确实是不同类型的规则,那么很多现有代码似乎都会崩溃。这大概也是其他编译器不符合标准的原因。
考虑到这一点,你的第二个问题的答案似乎是:
- 在编译时可能没有可移植的方法来执行此检查。当然,在翻译后,您可以随时查看对象文件,看看名称是否被篡改
但是在理论上,你的静态断言应该按照你认为的方式工作。实际情况并非如此。
附录:
如果我对标准的理解是正确的,那么例如下面的功能模板
template <typename R, typename... A>
void f(R(*)(A...));
无法实例化以生成接受指向具有C语言链接的函数的指针作为参数的函数,因为类型R(*)(A...)
是"指向具有C++语言链接的函数的指针,接受类型A...
的参数并返回R
"。
如果编译器真的是这样工作的,那么很容易看出如何通用地确定函数是否具有C或C++语言链接。
但这个例子也应该清楚地表明,如果编译器真的以这种方式工作,现有代码会有多糟糕。
- C++:如何使函数只返回作为列表一部分的字符串
- std::sort()函数无法对向量的一部分进行排序
- 反转整数的一部分(一半)的函数
- C++向量的哪一部分在传递给函数时被复制
- 如何正确实现 std::all_of 函数来验证字符串的一部分?
- 使用函数参数作为常量表达式的一部分 - gcc vs clang
- 关联容器,比较函数不是元素类型的一部分吗?
- 为什么函数的返回值不是符号名称的一部分
- 类型别名是否用作函数类型参数的一部分,是函数签名的一部分
- 函数的返回类型是损坏名称的一部分吗?
- c++为类和.cpp文件分离文件,函数不是类的一部分
- 为什么参数修饰符(即'const'或"易失性")不被视为函数类型或签名的一部分?
- 将哈希函数定义为结构的一部分
- 调用selectionsort函数只对数组的一部分进行排序
- 为什么"noexcept"说明符不是函数类型的一部分?
- 只手动定义复制构造函数和赋值运算符的一部分
- 访问作为WiFi侦听器回调成员函数一部分的类的成员
- 通过指向函数的指针循环传递数组的一部分
- 函数存储在内存的哪一部分
- 只有字符数组的一部分被打印与函数