I have two files main.c and header.c.
main.c has some macro STR who value I want to define conditionally according to some #define in the file.
Case 1:
When I include header.c in main.c file, the program is working fine as shown below:
main.c
#include<stdio.h>
#define _flag_b
#include "header.c"
void main(){
printf("%s", STR);
}
header.c
#ifndef _flag_a
#define STR "flag a is activated.\n"
#endif
#ifndef _flag_b
#define STR "flag b is activated.\n"
#endif
Compilation
anupam#g3:~/Desktop/OS 2020/so$ gcc main.c
anupam#g3:~/Desktop/OS 2020/so$ ./a.out
flag a is activated.
Case 2:
But for some reason, I want to include header.c in the compile command and not inside main.c. Which is creating this issue for me as shown below:
main.c
#include<stdio.h>
#define _flag_b
// #include "header.c"
void main(){
printf("%s", STR);
}
header.c
#ifndef _flag_a
#define STR "flag a is activated.\n"
#endif
#ifndef _flag_b
#define STR "flag b is activated.\n"
#endif
Compilation
anupam#g3:~/Desktop/OS 2020/so$ gcc main.c header.c
main.c: In function ‘main’:
main.c:7:15: error: ‘STR’ undeclared (first use in this function)
7 | printf("%s", STR);
| ^~~
main.c:7:15: note: each undeclared identifier is reported only once for each function it appears in
header.c:6: warning: "STR" redefined
6 | #define STR "flag b is activated.\n"
|
header.c:2: note: this is the location of the previous definition
2 | #define STR "flag a is activated.\n"
|
I have done a lot of research on this issue, and able to understand why the problem is arising. But I am not able to solve this issue.
Please help me in understanding this problem better and suggest some solutions to this. Also help me in rephrasing the problem.
#define defines a macro for a preprocessor - it means that before compilation, every instance of defined macro (after its definition) is replaced, in Your case after #define STR ... every instance of STR is replaced with specified constant. More about macros here
#include just copy a file and paste it in specified place. More about headers here
First example works because you included your header and code looks like this:
/*
stuff included by stdio.h
*/
int main(void) {
printf("%s", "flag a is activated.\n");
}
And it can compile easily. But in the second example you try to compile every file separately, so the first file looks like this:
/*
stuff included by stdio.h
*/
int main(void) {
printf("%s", STR); //preprocessor doesn't recognise STR as a macro
}
And the second file is empty. So now the compiler tries to compile it and it doesn't know what STR is, so you have an error.
If you want to keep it as a #define then you need to include the header.
You can read more about preprocessing here. If you want to see the output of preprocessor then you need to use a -E flag, for example: gcc main.c -E -o mainPreprocessed.c
Please, next time include code as a text, not an image - it will be easier for people to answer.
One more thing: *.c files are for code (that you add in your g++ command) and *.h files are for headers (that you include with #include).
Related
I am trying to generate function names dynamically with preprocessor directives (add a optional prefix).
The generation works and when gcc outputs me the code after the preprocessor (gcc -E), gcc tells me that the function has the right name.
But when i use this function in code, gcc throws an error with unresolved external symbol? (Link2019 / Link1120)
I'm not 100% sure how the linker works but theoretically gcc should run the preprocessor, build all the librarys (more exactly first the prototype and after the main the definition?) so there should be no problem?
Do i have to add a special compiler option? A link?
My main:
#define _CRT_SECURE_NO_WARNINGS
#define STRING_FUNCTION_PREFIX my // Defining a prefix for my string functions
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // Original string functions
#include "string.h" // My string functions
#define ARRAY_SIZE 50
#define HALLO "HALLO"
#define WELT "WELT"
int main()
{
char src1[ARRAY_SIZE], src2[ARRAY_SIZE], dst1[ARRAY_SIZE], dst2[ARRAY_SIZE];
strcpy(src1, HALLO);
strcpy(dst1, WELT);
strcpy(src2, HALLO);
strcpy(dst2, WELT);
strcat(src1, dst1);
mystrcat(src2, dst2);
return 0;
}
My string.h
#pragma once
#include <stdlib.h>
#if defined STRING_FUNCTION_PREFIX
#define FUNCTION_PASTER(ARG1,ARG2) ARG1 ## ARG2
#define FUNCTION_EVALUATER(ARG1,ARG2) FUNCTION_PASTER(ARG1, ARG2)
#define FUNCTION_NAME(FUNCTION) FUNCTION_EVALUATER(STRING_FUNCTION_PREFIX, FUNCTION)
#else
#define FUNCTION_NAME(FUNCTION) FUNCTION
#endif
/*
* \brief: Adds the string from src to the destination string
*/
void FUNCTION_NAME(strcat)(char *dst, char *src);
My string.c
#include "string.h"
void FUNCTION_NAME(strcat)(char *dst, char *src)
{
int counter = 0, offset = 0;
while (dst[offset] != '\0')
{
offset++;
}
dst[offset + counter] = src[counter];
}
Output for string.h when compiling with -E
1> #line 11 "d:\\string.h"
1>
1>
1>
1>
1> void mystrcat(char *dst, char *src);
Thanks for your Help!
The STRING_FUNCTION_PREFIX directive is defined in main.c, but not in string.c. So when string.c is compiled, the substitution does not occur. If you compile string.c with gcc -E, you'll see the effect of this.
You need to put #define STRING_FUNCTION_PREFIX my at the top of string.h instead of in main.c. That way, any .c file that needs it has it defined and it's consistent in all places.
You appear to be attempting to create an emulation of templates in C. If that is the case, you should treat the contents of string.c as a header file that needs to be included by someone that knows what value STRING_FUNCTION_PREFIX should be. If the string.c contents are a header file, rename it to make that clear, for instance, string_template.h.
Then, you can have a file mystring.c implemented as:
#define STRING_FUNCTION_PREFIX my
#include "string_template.h"
All across our C code base, I see every macro defined the following way:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
What is the rationale of doing these define checks instead of just defining the macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
I can't find this practice explained anywhere on the web.
This allows you to override the macros when you're compiling:
gcc -DMACRONAME=value
The definitions in the header file are used as defaults.
As I said in the comment, imagine this situation:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Will print 44.
However, if the conditional ifndef was not there, the result would be compilation warnings of MACRO redefinition and it will print 64.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
I do not know the context but this can be used to give the user the availability to override the values set by those macro definitions. If the user explicitly defines a different value for any of those macros it will be used instead of the values used here.
For instance in g++ you can use the -D flag during compilation to pass a value to a macro.
This is done so that the user of the header file can override the definitions from his/her code or from compiler's -D flag.
Any C project resides on multiple source files. When working on a single source file the checks seem to (and actually) have no point, but when working on a large C project, it's a good practice to check for existing defines before defining a constant. The idea is simple: you need the constant in that specific source file, but it may have been already defined in another.
You could think about a framework/library that gives to the user a default preset that allow the user to compile and work on it.
Those defines are spreaded in different files and the final user is advised to include it's config.h file where he can config its values.
If the user forgot some define the system can continue to work because of the preset.
Using
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
allows the user to define the value of the macro using the command line argument (in gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.
There is another important reason. It is an error to re-define a preprocessor macro differently. See this answer to another SO question. Without the #ifndef check, the compiler should produce an error if -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f is used as a command line argument in the compiler invocation.
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()
I am new to C programming. When I include the blank.h file into the Test.c file the program will not compile, however when I include blank.c file into the Test.c file it compiles fine. Below is the source for all the .c and .h files. Im using gcc as my compiler, and I have a feeling I need to do some sort of linking with it? Any help would be great thanks!
This is the Test.c source
#include <stdio.h>
#include "blank.h"
#include "boolean.h"
int main()
{
bool result = blank("");
printf("%d\n", result);
return 0;
}
This is the blank.h source
// Header file for blank function
bool blank(char string[]);
This is the blank.c source
#include "boolean.h"
#include "blank.h"
#include <regex.h>
bool blank(char string[])
{
regex_t regex_blank;
int blank = regcomp(®ex_blank, "[:blank:]", 0);
blank = regexec(®ex_blank, string, 0, NULL, 0);
if ( string == NULL || blank == 1 )
return true;
else
return false;
}
and finally the boolean.h
// Boolean
// Define true
#ifndef true
#define true 1
#endif
// Define false
#ifndef false
#define false 0
#endif
typedef int bool;
Ok, so I tried the source code you provided. There were a couple problems. Here are the exact steps of how I built, what I fixed. See if this works for you:
Created 4 files in a folder: Test.c, blank.c, blank.h and boolean.h
Copied code over.
From the shell ran:
gcc Test.c blank.c -o b
Output:
In file included from Test.c:2:0:
blank.h:3:1: error: unknown type name ‘bool’
blank.c: In function ‘blank’:
blank.c:11:46: error: ‘NULL’ undeclared (first use in this function)
blank.c:11:46: note: each undeclared identifier is reported only once for each function it appears in
To fix the first error:
In blank.h added this on top: #include "boolean.h"
To fix the second error:
In blank.c added this after the other includes: #include <stdlib.h>
Once again the terminal ran:
gcc Test.c blank.c -o b
then from the terminal ran ./b and it prints 1.
I suppose you are running GCC manually otherwise you wouldn't have that problem.
you can run GCC for each .c file manually or you can just run it for them all togather.
gcc *.c
if you do the later, you should not run into linker errors.
You forgot include guards:
blank.h:
#ifndef BLANK_H_INCLUDED
#define BLANK_H_INCLUDED
bool blank(char string[]);
#endif
These include guards prevent the contents of the header file being redefined each time a source file includes it. Make sure to do this for boolean.h too.
You need to include boolean.h in blank.h,
// Header file for blank function
#include "boolean.h"
bool blank(char string[]);
or you need to include it befor blank.h in Test.c, otherwise the compiler doesn't know the type bool in the declaration of blank.
Apart from that, the advice to always use include guards is good and should be followed.
Once removing the #include "blank.h" from Test.c and running gcc Test.c blank.c it compiled fine. Thank you for the advice on the include guards, and doing gcc Text.c blank.c
// File foo1.c :
#include <stdio.h> // once
void foo1(void);
void foo1(void){
puts("foo1");
}
// File foo2.c :
#include <stdio.h> // again
void foo2(void);
void foo2(void){
puts("foo2");
}
// File foomain.c :
#include <stdio.h> // yet again
void foo1(void); // again
void foo2(void); // again
int main(void){
foo1();
foo2();
puts("foomain");
return 0;
}
// create object files
gcc -fPIC foo1.c -o foo1.o // 1 stdio.h
gcc -fPIC foo2.c -o foo2.o // 1 stdio.h
// create shared library
gcc -fPIC -shared foo1.o foo2.o -o foo.so // foo.so contains stdio.h 2 times ?
// build entire program
gcc foo.so foomain.c -o foomain // foomain contains 1 stdio.h plus the 2 from foo.so ?
Why does the entire program contain 3 stdio.h ? Seems redundant, why not just 1 ? Shouldn't the compiler need only 1 ?
It makes sense for the object files to contain a prototype but why do they have to be specified again in foomain.c ? Shouldn't the compiler know they are already specified in foo.so ?
That's because each file is compiled separately, so each time the compiler should know the signatures of all functions used to perform compile-time checks. So, each file has to contain all declarations used, which are included by the preprocessor before the file is compiled.
If you look at the top of most header files they have an include guard to stop double inclusion.
#ifndef FOO
#define FOO
#endif
See Include Guard for more information.
The #include lines are not actually a part of the compiler, but the C preprocessor.
What the preprocessor does with #include lines is to actually include the file into the source, and creates a new temporary file containing the contents of your file with the #include line replaced by the contents of the file being included.
You don't actually need the include file at all, if all you are doing is calling functions. You might get warnings about the functions not being declared, but those can be adding the prototypes for those functions yourself. For example, in your main source file you only use puts, instead of including <stdio.h> you can add a prototype like this:
int puts(const char *s);
However, <stdio.h> also defines some structures (like the FILE structure) and declares some variables (like stdout) and if you use any of those you need the header file as well.
You can use include guards as #Jeff suggested or just put #pragma once at the top of each header.