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

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.

Related

C circular dependency with headers

I am working on a project where I have to follow guidelines on the organization of the files and I can't get it to compile.
To simplify it I have a main.h where I HAVE to define bool and some symbols to go along with it:
#ifndef main_h
#define main_h
#include <stdio.h>
#include "test.h"
typedef unsigned char bool;
#define TRUE 1
#define FALSE 0
#endif /* main_h */
Then the main.c HAS to use a type "num_seconds_t" and a function "test()", both of which have to be in a seperate file from main.
so I have my test.h:
#ifndef test_h
#define test_h
#include <stdio.h>
#include "main.h"
typedef int32_t num_seconds_t;
bool test(num_seconds_t var);
#endif /* test_h */
and my test.c:
#include "test.h"
bool test(num_seconds_t var){
num_seconds_t test = var;
return TRUE;
}
I don't think main.c would have any affect on this issue.
The error states unknown type "bool" in my test.h file, and I kind of understand why as when it hits the include for "test.h" within the main.h it starts going through that file before it has defined bool in main.h, then since main.h has "#ifndef main_h" when it hits "#include "main.h"" in the test.h it skips this and continues reading so bool never gets defined until after the test.h is done being read.
I am not sure if my understanding is correct, but what is the proper way of solving this. By simply moving the "#include "test.h"" to after the definition of bool it will compile, but in my big project I have many files that intertwine and coordinating the order of including these files would be very tough if not impossible.
Thanks
I'll present 3 solutions:
1) Your best option is to not #include test.h in main.h, since you don't need anything defined in test.h in main.h (you do need stuff from test.h in main.c, so test.h should be #includeed in main.c). This is good practice in general, as described in the comments (you don't want to #include something you don't need).
2) Your second best option is to move things from test.h and main.h to another file. In this case, you'd want to move your typedefs and #defines to another file like so:
typedef unsigned char bool;
#define TRUE 1
#define FALSE 0
typedef int32_t num_seconds_t;
and then include this file in main.h and test.h (or just in test.h because `main.h doesn't need these typedefs).
3) Your last and worst option is to carefully choose the order in which you include things. This is your worst option, since it gets very unwieldy with a large project, but I will show it nonetheless.
Leaving all your other files the same and doing:
// main.c
#include test.h
as the only include in main.c will solve your problem. When you try to compile this, only test.h will be #includeed in main.c. This will then include main.h, which has the typedefs you need for test.h. main.h won't include test.h again, since it has already been included. This is okay, because main.h doesn't actually need test.h.
You could also move your #include in main.h below your typedefs and include main.h in main.c. As I mentioned, however, option 3 is not a good option.
You should really do some combination of options 1 and 2 (in general, not just for this project).

include header files in C

I am a newbie to C and C++ language, I have a question about header files in C:
a.h
#define HELLO (1)
typedef struct
{
int a;
int b;
} hello;
b.h
#include "a.h"
#define NUMBER (3)
main.c
#include "b.h"
in main.c, does struct and macro defined in a.h can be used in main.c?
Sure you can use both Struct and MACROS in the main.c
You need to be aware of the C Compilation Process, Before main.c is being compiled or linked, there is the pre-processor step:
Preprocessor:
The input to this phase is the .c File and .h Files
The preprocess process the preprocessor keywords like #define, #ifdef, #include, etc. and generate a new .pre file or .i file after the text replacement process.
The output of this phase is a C Code without any preprocessor keyword.
So the main.c will actually look like this:
#define HELLO (1)
typedef struct
{
int a;
int b;
} hello;
#define NUMBER (3)
And then replace all macros, here you don't use HELLO or NUMBER, so the pure c main file will be:
typedef struct
{
int a;
int b;
} hello;
Yes, it can be used. That is the sole purpose of #includeing of header files.
For more information, you can see the preprocessed version of code. Use
gcc -E <filename.c> //main.c, in this case
There you can see the presence of the struct and MACROS definde in the included header files.
Yes, #include directives themselves appearing in included files have their normal effect, up to an implementation-defined limit on the number of levels of inclusion. The "normal effect" is equivalent to textual interpolation -- that is, there is no separate scoping for the contents of included files -- so any declaration appearing in any directly or indirectly included file is visible to all code following the point of inclusion.
Yep, #include statements can chain multiple files together. #include literally copies and pastes the contents of one file into another, so you can think of it as a one-after-another effect.

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()

Linking .h files with .c with #ifdef header guards

im having trouble linking .h and .c files, i've also read some threads regarding this problem and all of them is a bit vague and still i can't fully grasp the concept of it, and im having a lot of linking problems, Say i have b.c and b.h which i will use in a.c, and im confused whether to include b.h both a.c and b.c cuz b.c itself needs to know the structure defined in b.h, i have some function which has its prototype in b.h and is defined in b.c which also use the structure in b.h, im am not including b.h in b.c cuz as what i know b.h is more like an interface to a.c which will use the functions in b.c... Here a more clear example
b.h file
typedef struct{
int x, y;
}myStruct;
void funct1(myStruct);
void funct2(myStruct);
b.c file
void funct1(myStruct x)
{
//do something
}
void funct2(myStruct y)
{
//do something
}
a.c file
#include "b.h"
int main()
{
myStruct x;
funct1(x);
funct2(y);
return 0;
}
Executed the command in cygwin: gcc b.c a.c -g
Now the confusing part, i have a linking error wherein when b.c is compiled it can't detect the structure and the prototypes in b.h. Cuz all i know is that b.h is used to link b.c from a.c but when both .c is compiled it seems that b.c can't find its strucutre and prototypes,
Why didn't i include b.h in b.c?
Answer: Cuz as what i know, b.h is already included in a.c and when i include it again in b.c, i'll be doing double inclusions <--- thats what i learn so far and i know there is #ifdef but it seems it won't work, maybe i still don't know how to use it, if you know please feel free to discuss this.
If you have any idea as to how to go about this feel free to tell me some.
there is a #ifdef directive but i can't seem to have any idea how to do this.
NOTE: ASSUME THAT ALL ABOVE CODES IS SYNTACTICALLY CORRECT if there are any misspelled word please ignore, i'm only after the inclusions between .h and .c
You do indeed need to #include b.h in b.c. Each file is compiled separately before the linker takes over, so it doesn't matter that you have included b.h in a.c, because b.c is compiled by itself and has no idea about the contents of b.h unless you include it.
Here's an example of a #include guard
// some_header_file.h
#ifndef SOME_HEADER_FILE_H
#define SOME_HEADER_FILE_H
// your code
#endif
When some_header_file.h is included anywhere, everything in between the #ifndef and the #endif will be ignored if SOME_HEADER_FILE_H has been defined, which will happen on the first time it is included in the compilation unit.
It is common practice to name the #define after the name of the file, to ensure uniqueness within your project. I like to prefix it with the name of my project or namespace as well, to reduce the risk of clashes with other code.
NOTE: The same header file CAN be included multiple times within your project even with the above include guard, it just can't be included twice within the same compilation unit. This is demonstrated as follows:
// header1.h
#ifndef HEADER_H
#define HEADER_H
int test1 = 1;
#endif
// header2.h
#ifndef HEADER_H
#define HEADER_H
int test2 = 2;
#endif
Now let's see what happens when we try to include the above two files. In a single compilation unit:
// a.cpp
#include "header1.h"
#include "header2.h"
#include <iostream>
int main()
{
std::cout << test1;
std::cout << test2;
};
This generates a compiler error because test2 is not defined - it is ignored in header2.h because HEADER_H is already defined by the time that is included. Now if we include each header in separate compilation units:
// a.cpp
#include "header2.h"
int getTest2()
{
return test2;
};
// b.cpp
#include "header1.h"
#include <iostream>
int getTest2(); // forward declaration
int main()
{
std::cout << test1;
std::cout << getTest2();
};
It compiles fine and produces the expected output (1 and 2), even though we are including two files which both define HEADER_H.
You need to include b.h in all files that uses the structures that are defined in b.h. So you need to put a #include <b.h> in both files. To avoid that b.h is loaded several times, you need the directives #ifdef. In your case:
b.h
#ifndef B_H
#define B_H
typedef struct{
int x, y;
}myStruct;
void funct1(myStruct);
void funct2(myStruct);
#endif
and b.c:
#include "b.h"
void funct1(myStruct x)
{
//do something
}
void funct2(myStruct y)
{
//do something
}
Proper coding would have you include b.h in b.c.
Here is a header guard that should work:
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
//header file
#endif
Put your declarations where the comment is, and include everywhere you need to.
EDIT
The way I understand it, is that gcc compiles b.c first, because a.c depends on b.c. But when it compiles b.c first, b.h has not yet been included.
You need to #include b.h in b.c. It is not just an interface for a.c, b.c needs to know the same definitions for its own code as well. Your reason for not including b.h in b.c is wrong. Each .c file is compiled separately from every other .c file. When the compiler is done with a.c, it starts over fresh with b.c. It does not matter that a.c included b.h, because b.c has no concept that a.c even exists. The purpose of a header guard is to prevent a .h file from being processed repeat times if it is included multiple times while compiling a given .c file. Without the guard, declarations would get compiled multiple times, causing errors about multiple declarations of existing symbols.

Experimenting with global variables and functions in C

I'm trying to understand how global variables and functions work in C. My program compiles and works fine with gcc, but does not compile with g++. I have the following files:
globals.h:
int i;
void fun();
globals.c:
#include "stdlib.h"
#include "stdio.h"
void fun()
{
printf("global function\n");
}
main.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun();
int main()
{
i=1;
myfun();
return 0;
}
And finally, myfun.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun()
{
fun();
}
I get the following error when compiling with g++:
/tmp/ccoZxBg9.o:(.bss+0x0): multiple definition of `i'
/tmp/ccz8cPTA.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Any ideas why? I would prefer to compile with g++.
Every file you include globals.h from will define "int i".
Instead, put "extern int i;" into the header file and then put the actual definition of "int i = 1;" in globals.c.
Putting header guards around globals.h would be sensible too.
Edit: In answer to your question its because a #include works kind of like a cut and paste. It pastes the contents of the included file into the c file that you are calling include from. As you include "globals.h" from main.c and myfun.c you define int i = 1 in both files. This value, being global, gets put into the table of linkable values. If you have the same variable name twice then the linker won't be able to tell which one it needs and you get the error you are seeing. Instead by adding extern on the front in the header file you are telling each file that "int i" is defined somewhere else. Obviously, you need to define it somewhere else (and ONLY in one place) so defining it in globals.c makes perfect sense.
Hope that helps :)
I would add an include guard in your globals file
#ifndef GLOBALS_H
#define GLOBALS_H
int i;
void fun();
#endif
Edit: Change your globals to be like this (using extern as the other answer describes)
globals.h
extern int i;
extern void fun();
globals.c
#include "stdlib.h"
#include "stdio.h"
int i;
void fun()
{
printf("global function\n");
}
I compiled it with
g++ globals.c main.c myfun.c
and it ran ok
Several things wrong here; several other things highly recommended:
globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H
extern int my_global;
#ifdef __cplusplus
extern "C" {
#endif
void fun();
#ifdef __cplusplus
}
#endif
#endif
/* GLOBALS_H */
globals.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
int my_global;
void fun()
{
printf("global function: %d\n", my_global);
}
main.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
void myfun();
int main()
{
my_global=1;
myfun();
return 0;
}
void myfun()
{
fun();
}
You should declare "extern int myvar" in your header, and actually allocate "int myvar" in one and only one .c file.
You should include "globals.h" in every file that uses "myvar" - including the file where it's allocated.
Especially if you're planning on mixing C and C++ modules, you should use 'extern "C"' to distinguish non-C++ functions.
System headers should be "#include <some_header.h>"; your own headers should use quotes (#include "myheader.h") instead.
Short variable names like "i" might be OK for a strictly local variable (like a loop index), but you should always use longer, descriptive names whenever you can't avoid using a global variable.
I added a "printf" for my_global.
'Hope that helps!
I had this problem when porting some old C code to C++. The problem was it was a project that was connected to a database, and i wanted to port the database to c++ but not the rest. The database pulled in some C dependencies that couldn't be ported, so i needed the C code that overlapped both the database and the other project to compile in g++ as well as gcc...
The solution to this problem is to define all variables as extern in the .h file. then when you compile in either gcc or g++ it will report symbols missing in the .c files. So edit the .c files in the error messages and insert the declaration into all the .c files that need the variables. Note: you may have to declare it in multiple .c files, which is what threw me and why I was stuck on this problem for ages.
Anyway this solved my problem and the code compiles cleanly under both gcc and g++ now.

Resources