I am trying to find all places where #include is placed inside extern C block. Is is possible to check this using preprocessor? I would like to do add something like this to my header files:
#ifdef EXTERN_C_IS_IN_EFFECT
#error File included from extern "C" block!
#endif
I am also looking for other ways to fail compilation in such case, e.g. use some special attribute. I am using gcc 4.4.7.
I defined following macro and then use it in every header which needs protection against inclusion in extern C block:
#define ASSERT_NO_EXTERN_C void assert_no_extern_c(int); void assert_no_extern_c(double);
Maybe you can define 2 function prototypes with same name and different parameters. You will get warnings in case of extern "C" block. And it is allowed in C++.
That's not possible because the preprocessor runs before any syntactical analysis is done; that is, the preprocessor doesn't even know what extern "C" is and it's action cannot depend on the presence of such a directive either.
However, linkage specifications do nest, so instead of making sure the includer did not specify extern "C", you could place your header within an extern "C++" specification to make sure that it uses C++ linkage.
Related
I use macros like #DEBUG to print some additional debugging info and even possibly do something differently to help me with debugging. For example:
in header a.h:
#define DEBUG 1
in src a.c:
#include "a.h"
int func_a () {
/*some code*/
#if DEBUG
//do this
#endif
}
What will happen if I use a macro with the same name in another file ?
header b.h
#define DEBUG 1
#if DEBUG
# define PRINT 1
#elif
#define PRINT 0
#endif
src b.c
#include "a.h"
#include "b.h"
int func_b () {
/*some code*/
#if PRINT
//do this
#endif
/*some code*/
#if DEBUG
//do this
#endif
}
What will happen if I change the value of #DEBUG in one of the headers? I saw in some other answers that redefining a macro is not allowed in the C standard. But when I compile with GCC using the -Wall flag I see no errors or warnings.
What will happen if I use a macro with the same name in another file ?
It depends. C does not allow an identifier that is already defined as a macro name at some point in a translation unit to be defined again at that point, unless the redefinition specifies an identical replacement list. This is a language constraint, so conforming implementations will emit a diagnostic about violations they perceive. Compilers may reject code that contains violations, and if they nevertheless accept such code then the resulting behavior is undefined as far as C is concerned.
In practice, implementations that do accept such violations have two reasonable choices (and a universe of unreasonable ones):
ignore the redefinition, or
process the redefinition as if it were proceeded by an #undefine directive specifying the affected macro name.
Implementations of which I am aware accept such redefinitions and implement the latter option, at least by default.
If your headers are defining macros solely for their own internal use then you may be able to address the issue by exercising some discipline:
Each header puts all its #include directives at the beginning, before any definition of the possibly-conflicting macro(s).
Each header #undefines the possibly-conflicting macro at the end, under all conditional-compilation scenarios in which the macro may be defined in the first place.
On the other hand, if the macro is intended to be referenced by files that use the header(s) where it is defined then undefining it within the header would defeat the purpose. Under some circumstances, probably including yours, you can address that by defining the macro only conditionally in each header:
#if !defined(DEBUG)
#define DEBUG 1
#endif
That will avoid redefinition, instead using (only) the first definition encountered, which may even come from compiler command-line arguments. If you do this, however, it is essential that all the default definitions specified in that way be the same, else changing your headers' inclusion order will have unexpected effects code that depends on which definition is used.
I am trying to parse the syntax of a C file using pycparser. I send the C file through a preprocessor and then send the output of the preprocessor to be parsed by pycparser. The following code is in one of the C files ...
extern "asm"
{
extern void ASM_Function(void);
}
pycparser throws and exception telling me this is not valid C syntax. Looking at the C BNF the keyword extern does not allow a string literal to precede it. I am correct in reading the BNF? Was this extern functionality added in a later version of C or is this syntax compiler specific?
It looks like a compiler extension. Do you know what compiler the code was originally written for?
Most compilers support declaring a C calling convention by wrapping the function declaration with an:
#ifdef __cplusplus
extern "C" {
#endif
// functions that use C calling convention.
// are declared here.
#ifdef __cplusplus
} /* extern "C" */
#endif
The code appears to be declaring an externally defined assembly function called ASM_Function. You may be able to rewrite this if you know what is the calling convention the assembly function is expecting.
extern "C" is a C++ construct to declare functions that will not use name mangling and will use the cdecl calling convention.
EDIT: Corrected my post.
I'm somewhat confused by #define statements. In libraries, they seem to be a means of communication across different files, with lots of #ifdefs and #ifndefs.
Having said that, I now have two files file1.c and file2.c compiled together, with #define TEST 10 inside file2.c. Yet, when I use TEST inside file2.c the compiler gives the following error message:
'TEST' undeclared (first use in this function)
Are #define directives global?
#defines are not global, they are just a substitution where ever they are used (if declared in the same compile unit)
They are not globals, they are not symbols, they are irrelevant at linkage, they are only relevant at pre-compilation.
#defined macros are global in that they do not follow normal C scoping rules. The textual substitution from the macro will be applied (almost) anywhere the macro name appears after its #define. (Notable exceptions are if the macro name is part of a comment or part of a string literal.)
If you define a macro in a header file, any file that #includes that header file will inherit that macro (whether desired or not), unless the file explicitly undefines it afterward with #undef.
In your example, file2.c does not know about the TEST macro. How would it know to pick up the #define from file1.c? By magic? Since macros perform textual substitution on the source code, there is no representation of them in the generated object files. file2.c therefore needs to know that substitution rule itself, and if you want that shared across multiple files, that #define needs to live in a common header file that your .c files #include.
If you're asking specifically about how many of the #ifdefs that you see in libraries work, many of them are likely checking against pre-defined macro names provided by the compilation environment. For example, a C99 compiler defines a __STDC_VERSION__ macro that specifies the language version; a Microsoft compiler defines an _MSC_VER macro. (Often these predefined macros start with leading underscores since those names are reserved for the compiler.)
Additionally, most compilers allow defining simple macros as command-line arguments. For example, you might compile your code via gcc -DNDEBUG file1.c to compile file.c with NDEBUG defined to disable asserts.
In case somebody reads this later, and to add some practical information:
Some environments like atmel, vs, or iar, allow you to define global #define directives. They basically pass these defined values to the precompiler in some commandline format.
You can do the same in batch commands or makefiles, etc.
Arduino always adds a board variant (usually located at hardware\arduino\variants) to all compilations. At that point you can create a new board that contains your global define directives, and use it that way. For example, you can define a mega2560(debug) board out of the original mega2560 that contains some debug directives. You will add a reference to that variant in "boards.txt", by copy pasting some text, and properly modifying it.
At the end of the day, you will have to give that global hfile or global directive to the compiler in one way or another.
you should make a file1.h and put your defines there. Then in file2.c
#include "file1.h"
easy as a pie :)
I'm working on an embedded c project and am having issues with global variable redefinition.
I've split up the function declarations and definitions into a handful of .h and .c files. Many of these functions need access to global variables, which are defined in global_vars.h. Therefore, at the beginning of the header files, inside the #ifndef, #define section, "global_vars.h". If I don't, as you might imagine I get a bunch of undefined variable errors.
However, even though global_vars.h has the #ifndef _GLOBAL_VARS_H_ #define... #endif, I get redefinition errors for all the global variables. My guess is that when the linker tries link the various object files, it sees the redefinition due to the #include "global_vars.h" in all the "blah_blah.h" files. It was my understanding, though, that the #ifndef... takes care of this issue.
Is there something I'm overlooking?
Thanks in advance
The linker never sees anything in the global_vars.h file, ever, unless -- bad news! -- some of the globals are actually defined in that file. global_vars.h should hold only declarations of those global variables, never (well, almost never) their definitions.
In global_vars.h, you should have declarations like:
extern int some_global;
You are not allowed to have:
int some_global;
If you have definitions in global_vars.h then, yes, they'll be multiply defined at link time because each of the .c files that #includes global_vars.h will have its own definition of each defined variable.
All of the definitions of the extern globals must be in some .c file, for sure. Usually it doesn't matter which .c file. Often all of the global-variable definitions are in a file called (surprise!) global_vars.c.
So make sure there aren't any global-variable definitions in global_vars.h and you'll be in good shape.
Is not a good idea to define globals in an H file. Better if you do that in a C or C++ file and you include and H file in other modules with those globals as externals.
Like this>>>
My module c file
unsigned short int AGLOBAL = 10; // definer and initializer
void MyFunc(void)
{
AGLOBAL+=1; // no need to include anything here cause is defined above
// more .....
}
My H file globals.h
// this is to include only once
#ifndef MYH
#define MYH
extern unsigned short int AGLOBAL; // no value in here!
#endif
Other module c file
#include globals.h
char SomeOtherFunc(void)
{
AGLOBAL+=10; // ok cause its defined by globals.h
// do more....
}
So let me start with saying that extern keyword applies to C variables (data objects) and C functions. Basically extern keyword extends the visibility of the C variables and C functions. Probably that’s is the reason why it was named as extern.
Use of extern with C functions. By default, the declaration and definition of a C function have “extern” prepended with them. It means even though we don’t use extern with the declaration/definition of C functions, it is present there.
For example, when we write.
int foo(int arg1, char arg2);
There’s an extern present in the beginning which is hidden and the compiler treats it as below.
extern int foo(int arg1, char arg2);
Same is the case with the definition of a C function (Definition of a C function means writing the body of the function). Therefore whenever we define a C function, an extern is present there in the beginning of the function definition. Since the declaration can be done any number of times and definition can be done only once, we can notice that declaration of a function can be added in several C/H files or in a single C/H file several times. But we notice the actual definition of the function only once (i.e. in one file only). And as the extern extends the visibility to the whole program, the functions can be used (called) anywhere in any of the files of the whole program provided the declaration of the function is known. (By knowing the declaration of the function, C compiler knows that the definition of the function exists and it goes ahead to compile the program).
So that’s all about extern with C functions.
Declaration can be done any number of times but definition only once.
“extern” keyword is used to extend the visibility of variables/functions().
Since functions are visible through out the program by default. The use of extern is not needed in function declaration/definition. Its use is redundant.
When extern is used with a variable, it’s only declared not defined.
As an exception, when an extern variable is declared with initialization, it is taken as definition of the variable as well.
I want to define an inline function in a project, compiled with c99. How can I do it?
When I declare the function in a header file and give the detail in a .c file, the definition isn't recognized by other files. When I put the explicit function in a header file, I have a problem because all .o files who use it have a copy of the definition, so the linker gives me a "multiple definition" error.
What I am trying to do is something like:
header.h
inline void func()
{
do things...
}
lib1.c
#include "header.h"
...
lib2.c
#include "header.h"
with a utility which uses both lib1.o and lib2.o
Unfortunately not all compilers are completely complying to C99 in that point even if they claim that they'd be.
An conforming way to do this is
// header file. an inline definition alone is
// not supposed to generate an external symbol
inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
extern inline void toto(void);
Newer versions of gcc, e.g, will work fine with that.
You may get away with it for other compilers (pretenders) by defining something like
#ifdef PRETENDER
# define inlDec static
# define inlIns static
#else
# define inlDec
# define inlIns extern
#endif
// header file. an inline declaration alone is
// not supposed to generate an external symbol
inlDec inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
inlIns inline void toto(void);
Edit:
compilers with C99 support (usually option -std=c99) that I know of
gcc (versions >= 4.3 IIRC) implements
the correct inline model
pcc is also correct
ggc < 4.3 needs a special option to
implement the correct model,
otherwise they use their own model
that results in multiple defined
symbols if you are not careful
icc just emits symbols in every unit
if you don't take special care. But
these symbols are "weak" symbols, so
they don't generate a conflict. They
just blow up your code.
opencc, AFAIR, follows the old gcc specific model
clang doesn't emit symbols for inline functions at all, unless you have an extern declaration and you use the function pointer in one compilation unit.
tcc just ignores the inline keyword
If used by itself, in C99 inline requires that the function be defined in the same translation unit as it's being used (so, if you use it in lib1.c, it must be defined in lib1.c).
You can also declare a method as static inline (and put the definition in a header file shared between two source files). This avoids the multiple-definition issue, and lets the compiler inline the file across all the translation units where it's used (which it may or may not be able to do if you just declare the function in one translation unit).
See: http://www.greenend.org.uk/rjk/2003/03/inline.html
I think you don't need to use the inline word when you are defining and declaring the function inside the Header file, the compiler usually takes it as inline by default unless it's too long, in which case it will be smart enough to treat it as a normal function.
I think the multiple definition may be caused by the lack of a Include Guard in the Header file.
You should use something like this in the header:
#ifndef HEADERNAME_H
#define HEADERNAME_H
void func()
{
// do things...
}
#endif