Multiple #ifndef statements - which one gets applied - c

Say I have five files: main.c, sample1.c, sample1.h, sample2.c and sample2.h, where in each of these files DEBUG_PRINTS is defined as follows:
#ifndef DEBUG_PRINTS
#define DEBUG_PRINTS 0
#endif
and the code is compiled using gcc:
gcc -Wall main.c sample1.c sample2.c -o main
Now I change the value of DEBUG_PRINTS in one file to 1. Without printing to the terminal how can you determine, which value will be applied?
Additionally, how can I define DEBUG_PRINTS locally per file - the same as using the static keyword for variables?

Each file is compiled separately. Macros from one file are not visible in any other file. Once the files are independently compiled, the resulting objects are linked together to create an executable.

#ifndef means if the macro isn't defined at all in that file before or in an header you included. In your case, it defaults to 0.
If you change DEBUG_PRINTS in that one file to 1, it will override that #define in #ifndef found in the header file. You are basically locally defining or overriding the default DEBUG_PRINTS in the imported header file to 1.
Otherwise, macros are visible only to this file or header.

Related

How to stop the inclusion of file imported in a file , the file in which the latter has been included in C

Like a.c has the code
#include "b.h"
b.h has:
#include "c.h"
c.h has:
void fun()
{
}
here i want to restrict a.c from acessing fun but I want b.h to access c.h
If file A.c includes file B.h, and file B.h includes file C.h, and file C.h contains function func - then A can call func - this is just how the language works.
What you can do instead is to move C.h's import into a B.c - which isn't included in A.c - and thus prevent the inclusion of func in A.c. But then you have to separate B into .h and .c - and compile B.c explicitly.
As John pointed out in the comments, you should add include guards to every .h file, e.g.:
#ifndef _B_H_
#define _B_H_
...
#endif
This prevents function declarations from getting reincluded. Also - it is bad practice to implement functions (e.g. int func() { }) in your .h files - instead you should include only their definition (e.g. int func();) and move their implementation to a separate .c file.
In the first place, this ...
here i want to restrict a.c from acessing fun
... has nothing in particular to do with header files or #include. If fun is defined as an external function anywhere in the program, then it can be called from anywhere else in the program, headers notwithstanding. This is merely a question of knowing the function's name and at least something about its signature. With that information, any source file can provide its own compatible declaration of the function to enable the call (and some compilers might even accept the call without a declaration).
If you want to restrict the locations from which fun() can be called (directly, by name) then declare it static, and move its definition to the (only) C source file from which you want it to be callable.
As far as ...
How to stop the inclusion of file imported in a file , the file in
which the latter has been included in C
... goes, you can't do that, strictly speaking. If a.c contains an #include "b.h" directive that is processed, and, in the context of processing that directive, b.h contains an #include "c.h" directive that is processed then the effect is to include the contents of c.h in a.c. Period.
If b.h contains an #include directive that you want to avoid being processed under some circumstances then conditional compilation directives (#if, #ifdef, #ifndef) are the way to do so. "Include guards" are a particularly common example, and as a matter of style and convention, every header should guard its body via appropriate include guards. If your c.h did that then it would resolve the duplicate function definition error you get from a.c directly including both b.h and c.h:
c.h
#ifndef C_H
#define C_H
// everything else ...
#endif
Of course, b.h should have its own include guards, too.
But even more importantly, avoid putting function or variable definitions in header files in the first place. Put only declarations into header files (and provide prototypes):
void f(void);
The actual definitions belong in regular source files (.c), and regular source files should never be #included by any other file. This is the way to share declarations of external functions and objects among translation units without inviting duplicate definitions.

Macro used in a .c file getting compiled without adding the header file in which it is defined

I have a large project where some macro is defined as:
#define RECORD_COUNT 141 // in one file file1.h
Another file say file2.c is using this macro. But the file2.c is not including file1.h.
So is there a possibility that in on compiling the first file get pre-compiled is file1.h and the macro is added to the global scope. And this makes it possible to pre-compile the file2.c?
Very likely your macro definition are compiling before you are using it somewhere.
Just to check you can use pragma message to check if compiler touches that code.
http://msdn.microsoft.com/en-us/library/x7dkzch2.aspx
You do not need to include the header file directly to use it. There can be indirect includes as well.
For example,
Say file1.h has
#define RECORD_COUNT 141
file2.h has,
#include "file1.h"
...
...
If file2.c has #include "file2.h" then, you can use any macros or definition that are in 'file1.h' inside file2.c after that include statement.

EXPORT_SYMBOL in header causes "exported twice" errors

I have a header file with the declaration of several global variables in the following format:
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern unsigned var;
EXPORT_SYMBOL(var);
#endif
constants.c
#include "constants.h"
unsigned var = 10;
foo.c
#include "constants.h"
When I try to compile the kernel module, I get the following error for each respective exported symbol:
WARNING: /home/vilhelm/proj/constants: 'var' exported twice. Previous export was in /home/vilhelm/proj/foo.ko
I suspect that the symbols are being exported every time I include the constants.h header file, but I don't understand why. Shouldn't the include guard in constants.h prevent the EXPORT_SYMBOL(var) from being read multiple times?
Shouldn't the include guard in constants.h prevent the
EXPORT_SYMBOL(var) from being read multiple times?
The include guard prevents the header from being included more than once in the same source file. It can't prevent it from being included via multiple source files. Remember that the objects from all the sources get linked into a single object, and hence the conflict.
Let's say you have another header that is also included in the source files, called foo.h, which in turn includes constants.h. The file constants.c will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here, and constants.h will only be included once.
Same thing will happen with foo.c. It will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here too, and constants.h will only be included once.
But then the two objects, constants.o and foo.o will be linked together, each with its single copy of the EXPORT via constants.h. This adds up to two.
You want to make sure that exports appear in the final link just once. One way to do that would be to take them out of a common file like constants.h, and move them to a file called exports.c.

How to compile multiple .c and .h files in gcc linux?

So I have a source mainClass.c where I have the main defined. I have a header file class1.h and the implementation of all the functions defined in class1.h in class1.c. I have two variables (global) in class1.h named cond and mutex which are being used in class1.c for now and probably in future I will be using it in my mainClass.c as well.
Now to compile all the source files to generate one object file I am doing something as follows:
gcc -Wall -pthread -I/home/2008/ariarad/mainClass1 mainClass1.c class1.c -o out
/home/2008/ariarad/mainClass1 is where all my header and source files are at and I am using pthead.h in one of the .c file. Even though I have included it there it complains so I had to include it.
Now when I run the above command the I get the following errors:
class1.c:3:16: error: redefinition of ‘cond’
class1.h:66:16: note: previous definition of ‘cond’ was here
class1.c:4:17: error: redefinition of ‘mutex’
class1.h:67:17: note: previous definition of ‘mutex’ was here
Just in case I have an ifndef and endif block surrounding the class1.h to avoid multiple inclusion. I am definitely not redefining the variables defined in the header file in the .c file. So can someone please help me why it is still giving me the errors?
You cannot define global variables in header files. You must define them in one of the .c files, and then use extern in the header files:
In one of the .c files:
int cond;
In one of the .h files, which must be included by all .c files that need the variable:
extern int cond;

Why aren't my compile guards preventing multiple definition inclusions?

I have a header file x.h which is included by more than one *.c source files.
This header file has some structure variables defined.
I have put multiple inclusion prevention guard at the beginning of the header file as:
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
On building I get linker errors related to multiple definitions. I understand the problem.
Won't a multiple inclusion prevention guard at the top of header file as I have, prevent multiple inclusions of the header file x.h and thereby avoid multiple definitions of the variables that are there in x.h?
#pragma once does not work on this particular compiler, so what is the solution?
Someone had posted this answer to a similar question. It doesn't seem to work for me. How does this solution work?
If the linker is complaining, it means you have definitions rather than just declarations in your header. Here's an example of things that would be wrong.
#ifndef X_H
#define X_H
int myFunc()
{
return 42; // Wrong! definition in header.
}
int myVar; // Wrong! definition in header.
#endif
You should split this into source and header file like this:
Header:
#ifndef X_H
#define X_H
extern int myFunc();
extern int myVar;
#endif
C Source:
int myFunc()
{
return 42;
}
int myVar;
Header guards are only good for a single compilation unit, i.e., source file. If you happen to include a header file multiple times, perhaps because all headers included from main.c in turn include stdio.h then guards will help.
If you have the definition of a function f in x.h which is included by main.c and util.c, then it is like copying and pasting the definition of f into main.c when creating main.o and doing the same for util.c to create util.o. Then the linker will complain and this happens despite your header guards. Having multiple #include "x.h" statements in main.c is possible of course because of these guards.
Using include guards prevents one compilation unit from including the header twice. E.g. if header B.h includes A.h and B.cpp includes A.h and B.h, everything from A.h would be declared twice in the compilation B.cpp if you weren't using include guards.
Your include guards prevent this from happening, all's fine till now.
But you get multiple definitions at link time, i.e. two compilation units define the same thing, this probably means you got a real definition in your header, use extern for all variables, make sure functions are either inline or are defined in the cpp file.
If the functions aren't large, you can use "inline" before them and the linker won't complain.
Using a multiple inclusion guard prevents compiler errors, but you're getting a linker error. Do you have data definitions in the header file that don't use extern?
Maybe X_H is already defined somewhere else? I just ran into this issue, where Xlib defines X_H in /usr/include/X11/X.h.
To check, you can call gcc -dM -E (if you are using gcc), e.g. in the buildsystem I’m using that works with CC=gcc CFLAGS="-dM -E" make. If the output file contains #define X_H even though you remove it from your file (use Y_H for example), then it is already defined outside your source code.

Resources