A subtle consequence of the new rule for language linkage involves functions that take pointers to functions as parameters, such as
extern "C" void composer( int(*)(int) );
An unchanged rule about language linkage is that if you declare a function with language linkage, and follow it with a definition of the same function with no language linkage specified, the previous language linkage applies. For example:
extern "C" int f(int); int f(int i) { ... } // Has "C" linkage
In this example, function f has C linkage. The definition that follows the declaration (the declaration might be in a header file that gets included) inherits the linkage specification of the declaration. But suppose the function takes a parameter of type pointer-to-function, as in the following example:
extern "C" int g( int(*)(int) ); int g( int(*pf)(int) ) { ... } // Is this "C" or "C++" linkage?
Under the old rule, and with the 4.2 compiler, there is only one function g. Under the new rule, the first line declares a function g with C linkage that takes a pointer-to-function-with-C-linkage. The second line defines a function that takes a pointer-to-function-with-C++-linkage. The two functions are not the same; the second function has C++ linkage. Because linkage is part of the type of a pointer-to-function, the two lines refer to a pair of overloaded functions each called g. Code that depended on these being the same function breaks. Very likely, the code fails during compilation or linking.
It is a good programming practice to put the linkage specification on the function definition as well as on the declaration:
extern "C" int g( int(*)(int) ); extern "C" int g( int(*pf)(int) ) { ... }
You can further reduce confusion about types by using a typedef for the function parameter:
extern "C" {typedef int (*pfc)(int);} // ptr to C-linkage function extern "C" int g(pfc); extern "C" int g(pfc pf) { ... }