【问题标题】:Is `extern "C"` a part of the type of a function?`extern "C"` 是函数类型的一部分吗?
【发布时间】:2014-10-30 07:25:44
【问题描述】:

除了链接相关的东西之外,我在标准中没有看到任何评论。

虽然标准没有说明调用约定,但在现实世界中,C 和 C++ 之间的调用约定可能有所不同,所以我预计 C 函数和 C++ 函数的类型是不同的。但似乎不是,尤其是在 GCC 中。

#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");

static_assert 失败,因为 GCC 认为这些函数具有相同的类型。

  • extern "C" 是函数类型的一部分吗?
  • 如何检查函数是使用 C 调用约定还是 C++ 调用约定?

【问题讨论】:

  • C++ 支持例如函数重载。具有不同参数类型但名称相同的两个函数 - 它不能通过 C 链接完成,因为函数名称需要被修改以保持唯一。
  • @keltar 是的,你是对的,这不是我在这里要问的。这是关于调用约定,而不是名称修改。我在互联网上找到的关于 extern "c" 的每个文档和 Q/A 都提到了名称修改,而不是调用约定。
  • 因为它不能用于方法(因此不能影响 thiscall)- 是的,它应该只禁用修改而不修改约定,除非另有明确指定(例如使用 __attribute__ 编译器特定命令)。您比较的两种类型都是int (*)(int)
  • 也许有点不那么晦涩 - C++ 已经对普通函数使用了与 C 相同的约定(但是方法并非如此),所以这里没有什么可以改变的。但是,C 约定会随着您使用的 ABI 而变化,因此对于 C 和 C++,它在 32 位、64 位系统 V、64 位窗口等之间会有所不同。
  • @keltar 大多数 C++ 编译器会破坏一切,包括普通函数,除非被告知不要这样做。

标签: c++ c c++11 calling-convention


【解决方案1】:

标准清楚地表明语言链接确实是函数类型本身的属性:

所有函数类型、带有外部链接的函数名和带有外部链接的变量名都有一个 语言链接。

如果还不够清楚,有一个注释(强调我的)使预期的含义明确:

[注意:因为语言链接是函数类型的一部分,当通过指向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++ 语言链接。

但这个例子也应该清楚地表明,如果编译器真的以这种方式工作,现有代码会破坏多严重。

【讨论】:

    猜你喜欢
    • 2012-09-10
    • 1970-01-01
    • 2014-12-21
    • 2017-04-09
    • 2011-03-18
    • 1970-01-01
    • 2015-07-15
    • 2017-01-02
    • 1970-01-01
    相关资源
    最近更新 更多