传递给C库的函数指针的C链接 我的例子很简单:我希望我的C++程序能处理UNIX信号。为此,glibc在signal.h中提供了一个名为sigaction的函数,该函数期望接收一个函数指针作为其第二个参数 extern "C" { void uponSignal(int); } void uponSignal(int) { // set some flag to quit the program } static void installSignalHandler() { // initialize the signal handler static struct sigaction sighandler; memset( &sighandler, 0, sizeof(struct sigaction) ); sighandler.sa_handler = uponSignal; // install it sigaction( SIGINT, &sighandler, nullptr ); }

传递给C库的函数指针的C链接 我的例子很简单:我希望我的C++程序能处理UNIX信号。为此,glibc在signal.h中提供了一个名为sigaction的函数,该函数期望接收一个函数指针作为其第二个参数 extern "C" { void uponSignal(int); } void uponSignal(int) { // set some flag to quit the program } static void installSignalHandler() { // initialize the signal handler static struct sigaction sighandler; memset( &sighandler, 0, sizeof(struct sigaction) ); sighandler.sa_handler = uponSignal; // install it sigaction( SIGINT, &sighandler, nullptr ); },c++,c,signals,glibc,linkage,C++,C,Signals,Glibc,Linkage,我的问题是:extern“C”链接说明符是否必要 附加问题:uponSignal是否可以声明为static?extern C只有在您从二进制文件导出符号或从另一个二进制文件(通常在这两种情况下都是共享库)导入符号时才有必要,以避免名称损坏 这里不是这样,您没有跨各种二进制文件链接uponSignal,因此不需要extern C。您所做的只是将函数的地址从一个已经知道uponSignal地址的函数传递到sigaction,因为它们(显然)是同一翻译单元的一部分,或者至少是同一二进制的一部分 附加问

我的问题是:
extern“C”
链接说明符是否必要


附加问题:uponSignal是否可以声明为
static

extern C
只有在您从二进制文件导出符号或从另一个二进制文件(通常在这两种情况下都是共享库)导入符号时才有必要,以避免名称损坏

这里不是这样,您没有跨各种二进制文件链接
uponSignal
,因此不需要
extern C
。您所做的只是将函数的地址从一个已经知道
uponSignal
地址的函数传递到
sigaction
,因为它们(显然)是同一翻译单元的一部分,或者至少是同一二进制的一部分

附加问题:是否可以声明
uponSignal
静态

当然,如果你想的话
uponSignal
无论如何都不需要外部链接

我的问题是:
extern“C”
链接说明符是否必要

为了实现最大的可移植性,是的;C++标准只通过声明为“代码>外部”“C”<代码> >

函数来保证与C的互操作性。 实际上,没有;最明智的ABIs(包括GLUBC使用的GNU ABI)将使用C++和C++非成员(和静态成员)函数相同的调用约定,因此只需要在语言之间共享函数名即可使用<代码>外部“C”< /C>。 附加问题:
uponSignal
是否可以声明为静态


对。只需外部链接即可从其他翻译单元按名称访问该功能;没有必要通过函数指针调用函数。

实际上,我更担心调用约定而不是名称混乱。你不应该。;)尽管调用约定是特定于实现的(即,在标准范围之外),但我从未见过一个编译器不将调用约定作为函数签名的一部分,以便编译器在出现不匹配(无论如何很少发生)时向您发出警告。您是否有引用C++标准只通过声明外部函数“C”“.@”Qdii保证了与C的互操作性:实际上没有;没有明确说明没有保证的东西,只是提供保证的任何东西。7.5/1指定“两个不同语言链接的函数类型是不同类型的,即使它们是相同的”。,并有一个注释,指出“特定的语言链接可能与[…]特定的调用约定等相关联”。如果删除
extern“C”,某些编译器将干脆拒绝编译它因为SigAcess的第二个参数有错误类型。在许多编译器中,它们不考虑函数类型的链接部分是一个错误。