为什么不能对 C 函数进行名称修改?

新手上路,请多包涵

我最近接受了一次采访,其中一个问题是 extern "C" 在 C++ 代码中的用途。我回答说是在 C++ 代码中使用 C 函数,因为 C 不使用名称修饰。有人问我为什么 C 不使用名称修饰,老实说我无法回答。

我知道当 C++ 编译器编译函数时,它会给函数一个特殊的名称,主要是因为我们可以在 C++ 中重载必须在编译时解析的同名函数。在 C 中,函数的名称将保持不变,或者可能在其前面带有一个 _。

我的疑问是:允许 C++ 编译器也破坏 C 函数有什么问题?我会假设编译器给它们起什么名字并不重要。我们在 C 和 C++ 中以相同的方式调用函数。

原文由 Engineer999 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 711
2 个回答

上面有点回答了,但我会试着把事情放在上下文中。

首先,C是第一位的。因此,C 所做的就是“默认”。它不会破坏名称,因为它不会。函数名是函数名。全局就是全局,以此类推。

然后 C++ 出现了。 C++ 希望能够使用与 C 相同的链接器,并且能够与用 C 编写的代码进行链接。但是 C++ 不能让 C 的“修改”(或缺少)保持原样。查看以下示例:

 int function(int a);
int function();

在 C++ 中,这些是不同的函数,具有不同的主体。如果它们都没有被破坏,则两者都将被称为“函数”(或“_function”),并且链接器将抱怨符号的重新定义。 C++ 解决方案是将参数类型转换为函数名称。所以,一个叫做 _function_int 而另一个叫做 _function_void (不是实际的修改方案)并且避免了冲突。

现在我们面临一个问题。如果 int function(int a) 是在 C 模块中定义的,而我们只是在 C++ 代码中获取它的标头(即声明)并使用它,编译器将生成一条指令给链接器以导入 _function_int .当函数被定义时,在 C 模块中,它没有被调用。它被称为 _function 。这将导致链接器错误。

为避免该错误,在函数 声明 期间,我们告诉编译器它是一个旨在与 C 编译器链接或由 C 编译器编译的函数:

 extern "C" int function(int a);

C++ 编译器现在知道导入 _function 而不是 _function_int ,一切都很好。

原文由 Shachar Shemesh 发布,翻译遵循 CC BY-SA 3.0 许可协议

并不是说他们“不能”,一般来说,他们 _不是_。

如果你想在一个名为 foo(int x, const char *y) 的 C 库中调用一个函数,那么让你的 C++ 编译器将其修改为 foo_I_cCP() (或其他什么,只是当场编造一个修改方案)是不好的这里)只是因为它可以。

该名称无法解析,该函数位于 C 语言中,并且其名称不依赖于其参数类型列表。所以 C++ 编译器必须知道这一点,并将该函数标记为 C 以避免进行修改。

请记住,所述 C 函数可能位于您没有源代码的库中,您所拥有的只是预编译的二进制文件和标头。所以你的 C++ 编译器不能做“它自己的事情”,它毕竟不能改变库中的内容。

原文由 unwind 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题