tags:

views:

295

answers:

6

I found some code recently where extern "C" was added in source file also for functions. They were also added in the header files where they were declared.

I was under the assumption that adding 'extern "C" in header files was sufficient.

Where should extern "C" blocks be added?

UPDATE: Suppose I am compiling my C code using a CPP compiler and have added extern "C" guards for all the functions in header files (i.e. all my functions have their prototypes in headers), but in source files I have not added the same. Will this cause a problem?

+2  A: 

They should be added to all files, that get included in other files.

Normally, one doesn't include source files.

Georg
+9  A: 

They only need to go in anything that is included by other source files.

With some idioms you'll find people including source files.

Peter Alexander
++ for pointing to these idioms
Eli Bendersky
+2  A: 

You mean the 'extern c' preprocessors? They have to be on the function definition as well as that affects how the function call is stored in the compiled binary. Its only really needed if you are linking compiled c++ together with c which is compiled as C (as opposed to c in a .cpp file).

Remy
+2  A: 

Apologia

The question has changed to be much clearer what it was asking about. This answer addressed the original question, when it was at least debatable whether it was discussing guards against multiple inclusion in header files - which is what my answer addresses. Clearly, if the question had been as clear then as it is now, I would not have submitted this answer.


Original answer

No, it is not necessary to include the guards in the C code too.

If the header file 'header.h' says:

#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
...
#endif

Then it is perfectly safe for a source file 'source.c' to say:

#include "header.h"

It is also safe for other headers to include 'header.h'.

However, people note that opening a header file and reading it takes time, which slows up a compilation, so sometimes people do things like:

#ifndef HEADER_H_INCLUDED
#include "header.h"
#endif

This means that if some other header included in 'source.c' has already included 'header.h', then the '#include' is not re-processed. (Or, if 'header.h' has already been included directly in 'source.c', though that's a silly buglet.)

So, when encountered, it is likely to be an attempt to optimize the compilation performance. It is far from clear that it buys you much; modern C preprocessors are fairly intelligent about the issue and will avoid re-including the file if they can. And there's always a risk that the test in 'source.c' has a typo (#ifndef HEARER_H_INCLUDED, perhaps) in which case the test slows the compilation because the preprocessor tests the irrelevant condition and then proceeds to include 'header.h' after all. It is 'safe'; the header is itself protected-- or should be.

If you see the code in 'source.c' also doing '#define HEADER_H_INCLUDED', then there are problems. The #define has to be either before or after the #include, and neither is good as a general technique.

  • If 'source.c' does '#define HEADER_H_INCLUDED' before including 'header.h', then if the guard appears in 'header.h', the contents of the header will not be included. If the guard does not appear in 'header.h', then things work OK.
  • If 'source.c' does '#define HEADER_H_INCLUDED' after including 'header.h', then if the guard appears in 'header.h', we get a benign redefinition of HEADER_H_INCLUDED. If 'header.h' does not contain the guard but does include a file which includes 'header.h', you are not protected from multiple inclusion after all.

Note that body of the header appears after the '#define HEADER_H_INCLUDED'. This is again protection if nested includes include 'header.h'.

Jonathan Leffler
He's asking about `extern "C"`, not include guards.
jalf
@jalf: The question is now asking about 'extern "C"' guards; it wasn't clearly doing so yesterday when I answered.
Jonathan Leffler
I know. I just posted the comment for your information, so you had a chance to edit your answer to answer the question the OP actually meant to ask. :)
jalf
@jalf: OK - thanks for the heads up. I would probably have deferred to the other answers about 'extern "C"' rather than adding my own. I'll probably leave the answer as marked.
Jonathan Leffler
@Jonathan, My apologies to you for not making the question clear.
Jay
@Jay: NP - it is an occupational hazard when answering questions on SO. I don't mind minimal up-votes once the question is clarified; it was a nuisance to have a down-vote for it, but that was rescinded.
Jonathan Leffler
+7  A: 

Since you mean

extern "C" { ... }

style guards, these declare some functions to be of "C" linkage, rather than "C++" linkage (which typically has a bunch of extra name decoration to support things like overloaded functions).

The purpose, of course, is to allow C++ code to interface with C code, which is usually in a library. If the library's headers weren't written with C++ in mind, then they won't include the extern "C" guards for C++.

A C header written with C++ in mind will include something along the lines of

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

to make sure C++ programs see the correct linkage. However, not all libraries were written with C++ in mind, so sometimes you have to do

extern "C" {
#include "myclibrary.h"
}

to get the linkage correct. If the header file is provided by someone else then it's not good practice to change it (because then you can't update it easily), so it's better to wrap the header file with your own guard (possibly in your own header file).

extern "C" isn't (AFAIK) ANSI C, so can't be included in normal C code without the preprocessor guards.

In response to your edit:

If you are using a C++ compiler, and you declare a function as extern "C" in the header file, you do not need to also declare that function as extern "C" in the implementation file. From section 7.5 of the C++ standard (emphasis mine):

If two declarations of the same function or object specify different linkage-specifications (that is, the linkage-specifications of these declarations specify different string-literals), the program is ill-formed if the declarations appear in the same translation unit, and the one definition rule applies if the declarations appear in different translation units. Except for functions with C++ linkage, a function declaration without a linkage specification shall not precede the first linkage specification for that function. A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.

I'm not convinced it's good practice though, since there's the potential for the linkage specifications to diverge by accident (if, for example, the header file containing the linkage specification isn't included in the implementing file). I think it's better to be explicit in the implementation file.

Adam Bowen
What about static functions? There will be no declaration present in the header file, so should we be adding extern "C" for it in the source file? I am talking of a C Code being compiled using CPP Compiler.
Jay
Any function you need to link outside the current compilation unit must have the correct linkage declared. It doesn't matter for a static function (IE one that can only be seen inside the current c file) because the function is not exported, and so never needs to be linked to.
Adam Bowen
+1  A: 

The "C" guards have two purposes:

  1. When your code is compiled, the functions will be exported in a way that will allow a non C++ compiler/linker to use them (no C++ name mangling etc.)
  2. When a C++ compiler uses your header files, it will know that it should bind the symbols in the C way which in turn will make sure that the resulting program will link successfully. They don't carry a meaning for a non C++ compiler but since the symbols were generated in C-style in (1) this is the desired effect.

Since you include the header with the "C" guards also in your implementation file, the information on how the symbols should be created at compile time is available to the compiler and the compiler will create the symbols in a way that can be used by a non C++ compiler. Consequently you only need to specify extern "C" in your header file as long as the header file is also included by the implementation file.

VoidPointer
Does that mean for static functions which is not declared in header files, we need to add extern "C" guard in source files?
Jay
File-static functions will (and can-) not be called from external modules, there is no need to flag them for C-linkage. File-static function calls are resolved at compile time.
VoidPointer
But, suppose I try to compile my 'C' code using a C++ compiler. Will it still work?
Jay
Yes, C++ is (mostly) a superset of C.
VoidPointer