So, while being schooled by James Kanze and Loki Astari about C linkage, I was wondering about this:
extern "C" int foo1 (void (*)());
extern "C" { int foo2 (void (*)()); }
After my schooling, I think it must be that foo1
only takes a function pointer with C++ linkage, while foo2
only takes a function pointer with C linkage. Is my understanding correct? Are there specific references in the C++ standard that explain the differences in my example above?
Edit: To make it easier for everyone to follow along here's a pastebin with the relevant part from the C++ 11 draft standard.
The extern must be applied to all declarations in all files. (Global const variables have internal linkage by default.) extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block.
The block of code is called the body of the loop and is enclosed in braces and indented for readability. (The braces are not required if the body is composed of only ONE statement.)
The primary use of “extern” in header files is to allow C object modules to be linked into C++ programs. Since the methods of linking between the two languages are very different, one needs to alert a C++ linker that a module was compiled by a C compiler from C source and hence needs C linkage.
In a do-while loop, the do keyword is followed by curly braces { } containing the code statements. Then the condition is specified for the while loop.
foo1 takes a pointer to a C function as shown in [dcl.link] 7.5p4
In a linkage-specification, the specified language linkage applies to the function types of all function declarators, function names with external linkage, and variable names with external linkage declared within the linkage-specification. [Example:
extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function
The example applies directly to foo1
and the added emphasis highlights what I think is the reason. The function's parameter lists contains a function declarator for a parameter, and all function declarators are affected by the linkage specification. This applies to both braced and non-braced linkage specifications.
Some differences when not using braces are that names are automatically extern
and explicit use of a storage specifier is prohibited.
extern "C" int i; // not a definition
int main() {
i = 1; // error, no definition
}
extern "C" static void g(); // error
As an example of where this difference matters, consider a header containing the following:
extern "C" int a;
extern "C" double b;
extern "C" char c;
Someone might be tempted to change this to:
extern "C" {
int a;
double b;
char c;
}
But that would be incorrect because that converts the declarations into definitions. Instead the correct code using extern "C" {}
is:
extern "C" {
extern int a;
extern double b;
extern char c;
}
The braces are used when you have many declarations and definitions. Often you can see a start and end in header files for C
code to be usable in C++
#ifdef __cplusplus
extern "C" {
#endif
// C stuff here to be available for C++ code
#ifdef __cplusplus
}
#endif
I can recommend reading about "name mangling" http://en.wikipedia.org/wiki/Name_mangling The extern "C"
is a key to fallback to C
linkage name conventions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With