jxh
jxh

Reputation: 70402

Is there a difference between with braces or without when using extern "C"?

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.

Upvotes: 15

Views: 1965

Answers (3)

bames53
bames53

Reputation: 88155

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

Upvotes: 10

user9876
user9876

Reputation: 11102

extern "C" int foo1 (void (*)());
extern "C" { int foo2 (void (*)()); }

Those are the same. The main reason to use braces is if you have more than one function, e.g:

extern "C" int foo1 (void (*)());
extern "C" int foo2 (void (*)());
extern "C" int foo3 (void (*)());
extern "C" int foo4 (void (*)());

that can be written more simply as:

extern "C" {
    int foo1 (void (*)());
    int foo2 (void (*)());
    int foo3 (void (*)());
    int foo4 (void (*)());
}

Additionally, if you're trying to make one header file that works with both C and C++, you might want to write that as:

#ifdef __cplusplus
extern "C" {
#endif

    int foo1 (void (*)());
    int foo2 (void (*)());
    int foo3 (void (*)());
    int foo4 (void (*)());

#ifdef __cplusplus
}
#endif

P.S. I'm not aware of any compilers where there's a difference between "C++ linkage" or "C linkage" for function pointers. When we talk about C or C++ linkage, we're talking about how the name gets mangled by the compiler. For a function pointer, you're passing a pointer, so the name is irrelevant. It's important that the calling convention is the same, but it usually is the same for C and C++, since people freely mix those languages.

Upvotes: 1

epatel
epatel

Reputation: 46051

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.

Upvotes: 2

Related Questions