外部"C"静态void *功能

外部

问题描述:

在阅读了关于extern和static的内容之后,我很困惑地看到下面的代码:

After reading about extern and static, I am confused to come across the code which has the line below:

extern "C" static void* foo(int* a){
    return foo1(a);
}

为什么这不会产生任何错误?

Why does this not generate any error?

以下内容也可以编译并与您的行做同样的事情:

The following also compiles and does the same thing as your line:

extern "C" {
  static void* foo(int* a){
    return foo1(a);
  }
}

static 意味着 foo()仅在文件范围内可用,并且在出现时会覆盖 extern"C" 链接.通常,如果导出时, extern"C" 会影响链接器使用的函数的名称,以便在链接整个程序时可以从其他目标文件中调用该函数.通常,当您要链接到从C源构建的目标文件时,将使用此源,其中定义了 foo(),或者您想定义 foo(),因此C代码可以调用它.但是, static 导致根本不导出 foo ,因此它甚至根本没有名称(它具有 internal ,而不是外部链接.

The static means that foo() will only be available in file scope, and it overrides the extern "C" when it comes to linkage. Normally, extern "C" effects the name of the function used by the linker if/when it is exported, so that the function could be called from other object files when the entire program is linked. Usually, this is used when either you want to link to an object file built from C source where foo() was defined, or where you want to define foo() so that C code can call it. However, the static causes foo to simply not be exported at all, so it basically doesn't even get a name (it has internal, not external linkage).

外部"C" 也具有辅助作用.它也成为 foo type 的一部分.也就是说,C ++代码将看到 foo extern"C" void(int *)类型.基本上,这可以控制调用约定.C ++编译器例如与C编译器相比,在寄存器中/在堆栈上对参数的排列方式不同.使 foo 成为C函数意味着它将使用C约定而不是C ++约定.这样可以确保安全将指向 foo 的函数指针传递给C函数,该函数需要指向C函数的指针.例如,标准库有

extern "C" also has a secondary effect. It also becomes part of the type of foo. That is, C++ code will see foo as having type extern "C" void(int*). Basically, this controls calling convention. A C++ compiler may e.g. arrange arguments differently in registers/on the stack than a C compiler might. Making foo be a C function means that it will use the C conventions and not the C++ conventions. This makes it safe to e.g. pass a function pointer to foo to a C function that expects a pointer to a C function. For example, the standard library has

extern "C" typedef int C_CMP(void const*, void const*);
extern "C++" typedef int CXX_CMP(void const*, void const*);
void std::qsort(void *, std::size_t, std::size_t, C_CMP);
void std::qsort(void *, std::size_t, std::size_t, CXX_CMP);

使用外部"C" ,将& foo 传递给第一个重载,但没有它/使用外部"C ++" ,它将传递给第二个.如果不使用 extern"C" 声明 foo ,然后尝试将其传递给需要指向C函数的指针的C函数,那将是不安全的.它可能可能有效,但也可能会严重损坏.添加 extern"C" ,它正确无误,您很安全.

With the extern "C", &foo is passed to the first overload, but without it/with extern "C++", it is passed to the second. It would not be safe to declare foo without extern "C" and then try to pass it into a C function that expects a pointer to a C function. It would probably work, but it might also break horribly. Add the extern "C" and it becomes correct—you're safe.