Reputation: 433
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?
Upvotes: 13
Views: 6905
Reputation: 501
The following also compiles and does the same thing as your line:
extern "C" {
static void* foo(int* a){
return foo1(a);
}
}
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).
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);
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.
Upvotes: 9