Dynamic Functionname - Cannot resolve extern symbol - c

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"

Related

Compilation error while including header file in compile command

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

C Preprocessor include directive

When I include another source(I.e stdio.h) the preprocessor is smart enough to include only the functions that I am using in my code?
Example: Assuming this small program, would be ease to include only what I am using, and what the printf functions uses, including them recursively, but what about bigger programs?
#include <stdio.h>
int main(void) {
printf("Hello World\n");
return 0;
}
No. On the contrary:
#include performs textual replacement: it opens the file and copies all1 of its contents into your main C file. In the process it executes all preprocessor instructions in the included file. Amongst other things, this means that it will recursively include all files that are #included in the header.
#include does not know and does not care which part of the included file you end up using.
1 As mentioned, preprocessor instructions are executed in the included file. This can modify what gets included. For example, assume the following header file header.h:
#ifndef HEADER_H
#define HEADER_H
#ifdef NDEBUG
# define LOG(...) ((void) 0)
#else
# define LOG(...) log_message(__FILE__, __LINE__, __VA_ARGS__)
inline void log_message(const char* filename, int line, ...) {
// Logging code omitted for brevity.
}
#endif
// other stuff
#endif
Now, if your main.c file looks as follows:
#define NDEBUG
#include "header.h"
int main(void) {
// …
LOG("hello");
}
… then, after preprocessing, your main.c file would looks something like this (I’m omitting some irrelevant stuff):
# 1 "main.c"
# 1 "./header.h" 1
# 13 "./header.h"
// other stuff
# 3 "main.c" 2
int main(void) {
// …
((void) 0);
}
… in other words, only the part of header.h that corresponds to #ifdef NDEBUG was included, not the part in the #else clause. If we had included header.h without defining NDEBUG, then the included header code would have contained the definition of log_message.
As others have said, #include will paste verbatim the entire file you are targeting. However you normally include headers, which tend to look like
extern int a (int b);
extern char * c (void);
static inline int d (int e, int f) {
...
}
extern void * g (void * h);
...
The code above occupies exactly zero memory (unless you start using one of the inline functions), since it is entirely composed of instructions for the compiler and nothing else.

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.

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