哪些平台的C和C ++ ABI不兼容?

时间:2013-05-17 16:24:37

标签: c++ c abi

我刚才注意到C ++标准认为C和C ++函数具有不同且不兼容的类型,即使它们的类型签名相同(有关更多信息,请参阅this question)。这意味着您在技术上不允许将C ++函数传递给像pthread_create()这样的C函数。

我很好奇是否有任何平台在使用两个ABI实际上是不同的(除了显而易见的名称差异)。具体来说,有没有人知道这个C ++程序无法编译和运行的任何平台?

#include <assert.h>

extern "C" int run(int (*f)(int), int x) { return f(x); }

int times2(int x) { return x * 2; }

int main(int argc, char *argv[]) {
  int a = times2(argc);
  // This is undefined behavior according to C++ because I am passing an
  // "extern C++" function pointer to an "extern C" function.
  int b = run(&times2, argc);
  assert(a == b);
  return a;
}

1 个答案:

答案 0 :(得分:8)

我不知道ABI不同的任何平台,但即使C和C ++调用约定相同,C ++标准也要求编译器为程序发出诊断。指向函数的指针与C语言的链接是与指向函数的指针 - 与C ++ - 语言链接不同的类型,因此您应该能够像这样重载run():< / p>

extern "C" int run(int (*f)(int), int x) { return f(x); }
extern "C++" int run(int (*f)(int), int x) { return f(x); }

现在,当你调用run(times)时,它应该调用第二个,因此第一个不可调用(没有从指针到函数与C语言链接转换为指向函数的指针 - 与C ++ - 语言链接),因此原始代码应该导致编译器诊断。但是,大多数编译器都会出错。 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316

N.B。 Solaris编译器 诊断不兼容的语言链接,作为警告:

  

"t.c", line 11: Warning (Anachronism): Formal argument f of type extern "C" int(*)(int) in call to run(extern "C" int(*)(int), int) is being passed int(*)(int).

如果您使用run函数重载extern "C++",则会extern "C++"正确调用run(times)。{/ p>