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;
}