Scope and conditional #define in C - c

I want to use local .h file for define same names used in my lib. My lib has a default value definition for this names, but I'd like change this default value using local .h file. However, I'm having unwanted behaviour. How can I solve this?
test.c
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "conf.h"
#include "mylib.h"
int main ()
{
printf("Value in main: %d\n", NAMEDEFINITION);
fn();
return 0;
}
conf.h
#define NAMEDEFINITION 42
mylib.h
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#ifndef NAMEDEFINITION
#define NAMEDEFINITION 84
#endif
void fn();
mylib.c
#include "mylib.h"
void fn()
{
printf("Value in fn: %d\n", NAMEDEFINITION);
return;
}
My compiling line and output:
user#local:~/user/test/c$ gcc test.c mylib.c -o test
user#local:~/user/test/c$ ./test
Value in main: 42
Value in fn: 84
[EDITED]
I'd like NAMEDEFINITION be "42" when I define it in conf.h, then print "42" in two main() calls. When it is not defined in conf.h, it would be its default value, "84" (print "84" in two main() calls.

Value in main: 42
Reason for this is that in test.c you have included conf.h Now even though you include mylib.h, NAMEDEFINITION is visible in test.c and NAMEDEFINITION will have a value of 42. The ifdef in mylib.h will not be valid.
Value in fn: 84
In mylib.c you have not included conf.h. So the line #ifndef NAMEDEFINITION will be true and the value of NAMEDEFINITION will be 84.
If you want the value in fn to also print 42, you need to include conf.h in the mylib.c or mylib.h
Then if you comment out the line #define NAMEDEFINITION 42 in conf.h the value 84 will be printed both times.

I see 3 ways you could go with this:
1. Make config file mandatory part of your library
mylib.h
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "conf.h"
#ifndef NAMEDEFINITION
#error NAMEDEFINITION hasn't beed defined! Please edit conf.h!
#endif
void fn();
2. Define NAMEDEFINITION with compilation option
Example:
-D NAMEDEFINITION=42
With this approach you'd not use conf.h file at all. Downside to this method is that you have to make sure that you remember to include this option for your both .c file compilations.
3. Include conf.h with compilation option
Example:
-include conf.h
This is similar to method 2, but instead of defining symbol directly, you would force the inclusion of the conf.h instead.
What ever you do, make sure your header files have include guards. (Thanks #ChristianGibbons)

The explanation is very simple.
First example (main)
in the conf.h you define it. When you include mylib.h it is already defined and it is not redefined. So the value is 42
In the second example (fn) you just include mylib.h and #ifndef condition is true.
Macros are expanded before the compilation and are valid only in one compilation unit.,

Related

Are #define-s in a source file local to that object?

I'm unsure of the terminology, but I would like to know if in the following scenario, main.c has access to x.cs #defines:
/*x.h*/
#define ONE 1
/*x.c*/
#include "x.h"
#define TWO 2
/*main.c*/
#include "x.h"
int a = ONE;
int b = TWO;
You could just tell me to run gcc -o out main.c x.c if I want to know. But it might work, yet not be correct. This is why I am asking you. My goal is to have the #defines in x.c be local to that file, so they don't clash with any others in main.c. On the other hand, I do want #defines from x.h to be available to main.c because they need to be used when implementing the functions from x.c
Please advise
Your two .c files are equivalent to the following:
x.c :
#define ONE 1
#define TWO 2
main.c :
#define ONE 1
int a = ONE;
int b = TWO;
Any #define in a .c file will be local to that file. This is a common practice when optimizing code, leave a #define that is exclusively used in a .c file declared in that same c file.
Edit : BUT as #defines and #includes (and many other preprocessor directives) are expanded, this is done from top to bottom. meaning that one directive can then recieve #defines from some #include that was expanded earlier.
Here's an example of what I'm saying:
a.h :
#define A 1
b.h :
#define NEW_A A+1
main.c :
#include "a.h"
#include "b.h"
#include <stdio.h>
int main() {
printf("%i, %i\n", A, NEW_A);
return 0;
}
Will output:
1, 2
I'd suggest reading about compilation units and preprocessor directives in C.

gcc can't find define in header

I'm using a header called lib.h to organize my source code. The header is like:
#define TOT_REP 10
#define TOT_PAT 10
#define TIME_REP 15
The source file include the header, but when i compile with gcc i'm getting this:
error: ‘TIME_REP’ undeclared (first use in this function)
So i tried to compile with gcc -E -dM and i got something like this:
...
#define SIGUSR2 12
#define TIME_REP 15
#define ____mbstate_t_defined 1
#define __SIGRTMIN 32
...
I also tried with gcc -E and in the outuput i found that the macro is properly replaced with its value.
What can I do to solve this?
EDIT: The code where TIME_REP is used is this:
while((!ending|| *(shmAddress+0)!=0)&& quitSignal==0){
totFolder=0;
buf=(char*)calloc(2,sizeof(char));
patientString=(char*)calloc(2,sizeof(char));
sleep(TIME_REP);
while(read(fd,buf,sizeof(char))>0){
/*read from a file and get some data*/
}
}
EDIT 2: I tried to rename the lib.h and it seems to work now but i just can't understand why if with gcc -E -Dm found the macro then i can't compile the code.
Anyway to answer to Woodrow Barlow:
i have the lib.h and a rep.c the rep.c include the lib.h and other headers:
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>
#include "ReaderWriter.h"
#include "lib.h"
To compile I use gcc rep.c -o rep -Wall -pedantic

C preprocessor #error in header file included in multiple source files

I have two source files, main.c and datamgr.c - and two header files, config.h and datamgr.h
The testing system we're using expects these files, and only these files.
main.c:
#include "datamgr.h"
#include "config.h"
int main() {
custom_type a = 1;
a = foo();
return 0;
}
datamgr.c:
#include "datamgr.h"
#include "config.h"
custom_type foo() {
custom_type a = 1;
return a;
}
datamgr.h:
#ifndef DATAMGR_H
#define DATAMGR_H
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
custom_type foo();
#endif
config.h:
#ifndef CONFIG_H
#define CONFIG_H
#ifndef SET_MAX_TEMP
#error "Max temperature not set."
#endif
#ifndef SET_MIN_TEMP
#error "Max temperature not set."
#endif
typedef custom_type uint16_t
#endif
Now, the problem is that I can only define SET_MAX_TEMP and SET_MIN_TEMP in main.c, but both main.c and datamgr.c need both the header files. So if I leave them undefined in datamgr.c I get a compiler error. However, if I do define them in datamgr.c and later overwrite them in main.c, I get a different compiler error.
Please, any assistance as to how to get this horrible setup to work would be greatly appreciated.
You can pass these defines directly while compiling:
gcc -DSET_MAX_TEMP -DSET_MIN_TEMP <your files>
In datamgr.c do:
#define SET_MAX_TEMP
#define SET_MIN_TEMP
#include "datamgr.h"
#include "config.h"
#undef SET_MAX_TEMP
#undef SET_MIN_TEMP
In a comment, you said:
Because main.c is the file that our testing system uses to implement the test scenarios.
In that case, make sure that the testing system defines those macros in the command line of the compiler for every file being compiled.

Calling #define from another file

This is my code. I have file1.c and file2.c. I want to call the MESSAGE from file2.c but I can't seem to do it. I am newbie in C so I really don't know what to do. I researched already but, I can't seem to find a specific answer. Thankyou.
#define MESSAGE "this is message!"
helloworld(){
printf("%s",MESSAGE);
getch();
}
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file2.c"
int main(void)
{
helloworld();
}
There are a few misconceptions you have: First of all the concept of "calling" a macro. It's not possible, even if a macro looks like a function it's not a function and macros are not actually handled by the compiler. Instead macros are part of a separate language that is handled by a preprocessor, which takes the source file and modifies it to generate a translation unit that the compiler sees. (For more information about the difference phases of "compilation" see e.g. this reference.)
The preprocessor does this by basically doing a search-replace in the input source file: When it sees a macro "invocation" it simply replaces that with the "body" of the macro. When it sees an #include directive, it preprocesses the file and then puts the content in place of the directive.
So in your code, when the preprocessor sees the macro MESSAGE it is literally replaced by "this is message!". The actual compiler doesn't see MESSAGE at all, it only sees the string literal.
Another misconception is how you use the #include directive. You should not use it to include source files. Instead you compile the source files separately (which creates object files) and then link the generated object files together with whatever libraries are needed to form the final executable.
To solve the problem of macros (and other declarations) being available to all source files, you use header files. These are like source files, but only contains declarations and macros. You then include the header file in both source files, and both source files will know about the declarations and macros available in the header file.
So in your case you should have three files: The main source file, the source file containing the function, and a header file containing the macro and the function declaration (also known as a prototype). Something like
Header file, e.g. header.h:
// First an include guard (see e.g. https://en.wikipedia.org/wiki/Include_guard)
#ifndef HEADER_H
#define HEADER_H
// Define the macro, if it needs to be used by all source files
// including this header file
#define MESSAGE "this is message!"
// Declare a function prototype so it can be used from other
// source files
void helloworld();
#endif
Main source file, e.g. main.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
int main(void)
{
// Use the macro
printf("From main, MESSAGE = %s\n", MESSAGE);
// Call the function from the other file
helloworld();
}
The other file, e.g. hello.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
void helloworld(void)
{
printf("Hello world!\n");
printf("From helloworld, MESSAGE = %s\n", MESSAGE);
}
Now, if you use a command-line compiler like gcc or clang then you can simply build it all by doing e.g.
$ gcc -Wall main.c hello.c -o myhello
That command will take the two source files, main.c and hello.c and run the preprocessor and compiler on them to generate (temporary) object files. These object files are then linked together with the standard C library to form the program myhello (that's what the option -o does, names the output file).
You can then run myhello:
$ ./myhello
From main, MESSAGE = this is message!
Hello world!
From helloworld, MESSAGE = this is message!
In your file1.c, MESSAGE is a preprocessor macro, which means the text MESSAGE will be replaced with the string "this is message!". It is not visible outside the file. This is because in C, translation units are the final inputs to the compiler, and thes translation units already have all of preprocessor macros replaced by the tokens of the corresponding argument.
If you want to have a common variable, you should declare the variable as extern in a .h header file, and then #include the file where you need to use it.
see Compiling multiple C files in a program
You have to put your #define in a .h file and include it in .c files where you want to use it.
You can write the files as below and compile the code as i mention in the following steps.
file1.h
#ifndef _FILE1_H
#define _FILE1_H
#define MESSAGE "this is message!"
extern void helloworld();
#endif
file1.c
#include "file1.h"
helloworld()
{
printf("%s",MESSAGE);
getch();
}
file2.c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file1.h"
int main(void)
{
helloworld();
return 0;
}
For compiling,
gcc -Wall file1.c file2.c -o myprog
./myprog
Here is code try this:
In File1.C
#define FILE1_C
#include "file1.h"
helloworld()
{
printf("%s",MESSAGE);
getch();
}
In File2.C
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file1.h"
int main(void)
{
helloworld();
}
In File1.h
#ifdef FILE1_C
#define MESSAGE "this is message!"
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN helloword()

C preprocessor directive error

I have a problem when i want use his scripts:
lib1.h
...
#ifdef LIB1_01
int lib1func(void);
#endif
...
lib1.c
...
#ifdef LIB1_01
int lib1func(void){
...
}
#endif
...
main.c
#define LIB1_01
#include <lib1.h>
int main(){
...
int x = lib1func(void);
...
...
I want use lib1func() when #define LIB1_01 is declared but I have an 'warning : implicit declaration of function' error when i use it...why ? Can you help me ?
Best regards.
Recommended alternative:
lib1.h
#ifndef LIB1_H
#define LIB1_H
int lib1func(void);
#endif
...
lib1.c
#include "lib1.h"
int lib1func(void){
...
}
main.c
#include "lib1.h"
int main(){
...
int x = lib1func(void);
...
...
NOTE:
1) You should declare "int lib1func(void)" in the header, but you may define it anywhere. In lib1.c (if you prefer), or even main.c. Just make sure you only define it once.
2) Note the use of the guard around the entire header body.
3) Also note the use of include "myheader.h" (for your own header files), vs. #include <systemheader.h>. The "<>" syntax should be used only for system headers.
To use that kind of includes, compile with option I.
gcc myfile.c -o myfile -I .
The . symbol means look in the current directory.

Resources