#define scope in multiple files - c

I have a main file like so:
main_a.c:
#define MAIN_A
#include <stdio.h>
#include "shared.h"
extern int i;
int main() {
printf("i is: %d\n", i);
return 0;
}
I want to use the define in shared.h like this:
shared.h
#if defined(MAIN_A)
# define A
#endif
So I can declare a variable according to whether the main file is present or not, like this:
shared.c
#include "shared.h"
#if defined(A)
int i = 1;
#else
int i = 0;
#endif
I build it using a makefile which looks like this:
Makefile:
all : a
./a
a : main_a.o shared.o
gcc -o $# $^
%.o : %.c
gcc -c $<
However this prints
i is: 0
Now my question is: Why is it that the define seems to be lost when I compile the shared module? I know the main module is compiled first, so the define should have been resolved by the time shared.c is compiled.
One suspicion I have is that the preprocessor might get run at the start of each module build and not just at the start of the project. If this is correct is there a way of compiling more than a single module at a time to use the preprocessor as I attempt above?

Preprocessor is run for each file before it is compiled, i.e. once for main_a.c and then again independently for shared.c. When shared.c is compiled MAIN_A is undefined.
Preprocessor can't be used the way you're attempting, i.e. remembering state across compilation units.
What you can do is define a name (for example MAIN_A) using the -Dcompiler option in your Makefile and test this name using preprocessor the same way you're doing it now. This way the definition takes place on the project level (in the Makefile) rather than on a compilation unit level (in a .c file).

Let me do the preprocessor's work here and expand all your macros. In main.c, MAIN_A is defined, so A is defined. Nothing depends on A in main.c, and i is extern.
In shared.c, MAIN_A and thereby A are undefined, and i is 0.
In short, the preprocessor cannot transport information between compilation units. That's good practice, because otherwise programs would quickly become unreadable and you would have to recompile all compilation units when one unit changes (because symbols might have changed). Resolve the issue by setting i explicitly in main:
int main() {
i = 1;
}
It is more verbose, but is also much clearer to the reader. If you want to encapsulate, define a function InitializeShared. If you truly want to compile some code as a single compilation unit, make one of the files a header file and #include it into the other.

Yes you are right, they are completely separate compilation units.
MAIN_A is only defined in main_a.c
One thought that comes to mind is to cat the files together to make one compilation unit?

Global define A
gcc main_a.c shared.c -DA

Defines almost work the same as any variable. If you want to share a variable across modules, you put it in a header. Same goes for #defines.
However, it is strange to use the #ifdef as you are always going to have main.c. You don't want to change the code each time you compile. Instead, use the method described by Adam Zalcman

Related

Is it possible to compile multiple dependent C files, without creating header file?

I am having some issues with putting multiple .c files together.
I will mimic my situation with the following files.
mod.c
#include <stdio.h>
void print_hello() {
printf("Hello!");
}
mod_main.c
#include "mod.c"
int main() {
print_hello();
}
Compiling scenarios:
#1
$ cc -o mod_main mod_main.c
# No errors
#2
$ cc -c -o mod_main.o mod_main.c
$ cc -c -o mod.o mod.c
$ cc -o mod_main mod.o mod_main.o
duplicate symbol '_print_hello' in:
mod.o
mod_main.o
ld: 1 duplicate symbol for architecture x86_64
#3
$ cc -o mod_main mod.c mod_main.c
duplicate symbol '_print_hello' in:
Based on these attempts, I gather that, I can compile simply mod_main.c & get it working. Or, I can create a .h file as follows & get it working.
mod.h
void print_hello(void);
mod.c
#include <stdio.h>
#include "mod.h"
void print_hello() {
printf("Hello!");
}
mod_main.c
#include "mod.h"
int main() {
print_hello();
}
I like to know, if there are any other ways to compile multiple C files that has dependencies within each other. To be precise, is there a decent way to avoid writing header files?
Good day!
PS: I have explored similar questions on StackOverflow. None of them that I could find where asking the exact questions as mine.
First of all, including source files is generally a bad idea.
As for the problem itself, you can easily solve it by pretending you're writing a header file, but instead write all declarations, structure definitions and macros in a source file. Then copy-paste it into the other source files who needs it.
But, and this is a very important but, this is extremely error-prone. If the signature (e.g. argument list) of a function changes, or a structure is modified, or a macro gets a different value, then you must remember to modify this everywhere. If you have more than a couple of source files it becomes easy to miss one of the files.
If a function with the wrong signature is called, or you have structures that are not character-by-character copies of each other, then that will lead to undefined behavior. Mismatching macros might not be so serious, but if it's an array-limit that is changed (for example) then it's easy to go out of bounds where you miss to update the macro.
In short: It's possible, but not a good idea. Use one or more header files for common declarations, structures and macros.

Prevent inclusion of stdio.h (or other standard header)

A codebase I work with has historically tried--purposefully--to avoid dependencies on stdio.h creeping in. It has its own print formatting and mechanisms, and those are what's supposed to be used instead of printf etc.
But someone adds a dependency every so often that has to get noticed and taken out. So I tried to make an alarm for the easiest of cases:
#if !defined(NDEBUG)
void printf(float dont_link_with_stdio_h);
#endif
The gcc people seem to have been thinking along the lines of stopping easy errors too, because there's a helpful message if you do this...whether you've included <stdio.h> or not.
conflicting types for built-in function 'printf'
There's a way to turn this warning off (-fno-builtin). And there are all kinds of approaches that would do things like filter the symbol dump for things you don't want to be there...
But is there a trivially easy non-warning-causing (if you didn't include stdio.h) way to alert someone that they've introduced an unwanted printf usage?
You can redefine printf to be some nasty value that will cause a compilation or linking error. For example:
#define printf do_not_include_stdio_h
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
return 0;
}
produces the output:
undefined reference to `do_not_include_stdio_h'
You can munge the macro if you want it to be an even more obscure name or include invalid symbols if you're worried that some poor soul will have defined do_not_include_stdio_h.
You can set the macro definition in the compiler flags so you don't have to manually edit the file(s). For example:
gcc -Dprintf=do_not_include_stdio_h my_file.c
I wouldn't touch the source files at all. I'd modify the build script. Much easier to maintain, and much easier to prevent people from circumventing the restriction (e.g. by changing the code which causes compilation to fail).
For example, in a makefile, assuming you have an all target that build everything
all:
grep stdio *.h *.c
if ["$?" -eq 0 ]; then
echo "Do not use stdio. Contact Joe for info"; exit 2;
fi
<other stuff to do the build here>
You can also do it on particular targets. For example, if you have a target that compiles a .c file to produce a .o file, just check the .c file before compiling it.
%.o : %.c
grep stdio $<
if ["$?" -eq 0 ]; then
echo "Do not use stdio. Contact Joe for info"; exit 2;
fi
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
Your only problem now is what to do if you have someone who is determined to bypass your restriction (e.g. by #include "bypass.joe" where bypass.joe has an #include <stdio.h>). For that, look up tools to generate dependencies (e.g. gcc -MM, makedepend, etc) and use that to set up a way to search all of the files your source files depend on. If someone is that determined, also set protections on your makefiles so only you can edit them.
EDIT: If you have a tool set up to generate a dependency file, simply search that file for stdio. If any compilation unit, directly or indirectly, includes stdio.h , then it will be listed in the dependency file.
To prevent inclusion of <stdio.h>, I would go with
#if !defined(NDEBUG)
#if defined(EOF)
#error Do not include stdio.h, contact Joe for more information
#endif
#endif

How to #include a different file each time based on user input?

I have a program which, depending on the user input, #includes one header headerA.h or another headerB.h I expect the header to be there till the end of the program.
headerA and headerB define structures with the same names but with different fields, and I'm not able to merge both files in one, and neither able to change anything else from the libraries that headerA and headerB are using.
Is there a way to solve this problem?
Preprocessor macros:
#if defined(USE_HEADERA)
# include "headerA.h"
#elif defined(USE_HEADERB)
# include "headerB.h"
#else
# error must define USE_HEADERA or USE_HEADERB
#endif
If you have GCC then you tell the preprocessor which to select using the GCC -D option:
$ gcc -DUSE_HEADERA myfile.c -o myprogram
However, if you want to do it runtime during execution that's impossible. #include is a preprocessor directive, and the preprocessor only runs as part of the compilation.
Although it is possible to conditionally include files, it does not seem to be possible to have this change during runtime. See this answer about it. The if statements only work before runtime.
I don't think it is possible as your #includes are resolved before compilation i.e during preprocessing. So it is not possible to change them during runtime.
But you can try conditional compilation by defining a macro during compiletime.
#ifdef HEADERA
#include <headerA>
#ifdef HEADERB
#include <headerA>
While compilinging gcc
$ gcc prog.c -DHEADERA to include headerA or vice versa

Conditional compilation: compile once if macro is present at least once

I'm writing a C program and would like to write a function so that, if a certain macro is used at least once, the function is compiled in the object file exactly once.
I was thinking of something in these lines:
#define CERTAIN_MACRO \
...some code here... \
#include "myfunction.h"
(adding my function code in myfunction.h, with suitable include guards in order to prevent multiple inclusion), or
#define CERTAIN_MACRO \
...some code here... \
#define USE_MY_FUNCTION
#ifdef USE_MY_FUNCTION
my function code
#endif
But neither works, because #define and #include are not allowed in macro-expanded code. Any suggestions?
Let the linker do the job it's meant to.
Place the function into its own source file and then build that into a library, say liboptional.a.
When it comes time to create the executable, use that library, for example:
gcc -o execfile file1.o file2.o -loptional
At the time the linker sees the -l optional, it will use the objects within that library to satisfy undefined references. Hence, if you're used the function in file1.o or file2.o, it will be included.

How to prevent multiple definitions in C?

I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks
int main()
{
//t = test(); // calling of method also not necessary
return 0;
}
test.c:
void test() {}
When I try to build this program, it gives the following errors:
*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|
There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.
I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.
Does anyone know what is causing this and what I can do about it? Thanks!
You actually compile the source code of test.c twice:
The first time when compiling test.c itself,
The second time when compiling main.c which includes all the test.c source.
What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:
void test(void);
This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.
In main.c, replace #include "test.c" by #include "test.h".
A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
void test(void);
#endif
The underscore is put there by the compiler and used by the linker. The basic path is:
main.c
test.h ---> [compiler] ---> main.o --+
|
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe
So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:
void test(void);
This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.
It's the linking phase that joins together the two modules.
By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().
You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.
The error is caused by multiple definitions of the test function (one in test.c and other in main.c)
I had similar problem and i solved it following way.
Solve as follows:
Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.
Function definition and use of global variable in test.c file
if you initialize global variables in header it will have following error
multiple definition of `_ test'|
obj\Debug\main.o:path\test.c|1|first defined here|
Just declarations of global variables in Header file no initialization should work.
Hope it helps
Cheers
Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:
/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:
remove the #include "test.c"
create a file test.h which contains the declaration:
void test();
include the file test.h in main.c
If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well ..
.. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.
Good luck with it
Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.
I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)
The solution was to ONLY put a declaration in the header file and the definition in the cpp file.
The reason is that header files are not compiled, they only provide definitions.

Resources