I'm writing a C program where I use a header to declare some functions and define several constants. When I use these constants in my code, I get the error Symbol 'FOO' could not be resolved. I have no problems with the declared functions.
I am using Eclipse Neon. I have already verified that the path to the directory containing the header files is added to the Include Path. And I have also restarted Eclipse.
header.h
#ifndef __header_h_
#define __header_h_
#define FOO 0x00
#define BAR 0x01
void do_stuff(int x);
#endif
main.c
#include <stdio.h>
#include "header.h"
int main() {
do_stuff(FOO);
return 0;
}
ERROR: Symbol 'FOO' could not be resolved
What am I missing here?
Right Click on the Project Index > Freshen All Files and then Index > Rebuild fixed the problem
Related
I have the problem, that in CCS I encounter unexpected redefenition errors if I include headers.
Minimal example:
// main.c
#include "test.h"
int main(void)
{
init();
return 0;
}
with
// test.h
#ifndef TEST_H_
#define TEST_H_
int var;
void init();
#endif /* TEST_H_ */
and
// test.c
#include "test.h"
void init()
{
var=0;
}
I get
error #10056: symbol "_var" redefined: first defined in "./main.obj";
redefined in "./test.obj"
on compilation. I'm pretty sure this should work in any C using IDE.
What do I miss?
" I'm pretty sure this should work in any C using IDE". No it doesn't.
Every time you include test.h in a C file, the variable var is not only declared but also defined, hence the compilation error.
Include guards are not designed to avoid multiple definitions across translation units, but more to adress multiple inclusions of the same header file in a single translation unit.
See for example https://fr.wikipedia.org/wiki/Include_guard
The proper way to adress this issue is to only declare your variable in the header file:
extern int var;
and then define the variable only once in a C file (without extern).
int var;
below is the code:
//test.h
...
extern int globalVariable;
...
//test.c
#include "test.h"
...
int globalVariable = 2020;
...
//main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("Value is %d", globalVariable);
}
let's say in a scenario, there are hundreds of variables are declared in test.h and globalVariable is just one of them.
since there are two many variables, I easily makes a typo error in test.c as:
#include "test.h"
int globalVariables = 2020; //extra 's' in the name which contradicts the declaration of its counterpart in test.h
if I compile(only compile,not linking them) test.c, test.h and main.c, it compiles and shows no error. the unresolved error will only occur when linker involved in the linking stage.
But in a large application, I might just write some modules without the need of linking all existing to an executable file, so it would be better the compiler throw an error in the compile stage to indicate the error so I can correct them asap, so how can I let the compiler force the source file implement definition for a header file?
You could also use the preprocessor
test.h:
#ifndef TEST_C_IMPLEMENTATION
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
extern type name;
#else
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
type name = value;
#endif
DEFINE_AND_INIT_VARIABLE(int, globalVariable, 2020);
test.c:
#define TEST_C_IMPLEMENTATION
#include "test.h"
This technique can be taken even further - there are small utility libraries that are shipped as a single include file; you're just to set a macro in one of the translation units to force the implementation to be compiled in there.
The declaration extern int globalVariable; says that the variable exists somewhere, but not necessarily in the current translation unit. So any source file that includes the header containing this declaration will know that the variable exists without needing the full definition.
When you then get to the linking stage is when you'll get the error regarding glovalVariable being undefined. Since the variables is declared in test.h, convention would dictate that the definition would be in test.c. Upon inspecting that file, you would then find that no such variable exists and could then either add it or find the typo and fix it.
I am programming a game in C using Code::Blocks. I am using the most recent version of C and of Code::Blocks. I am still learning the language.
All of my past programs have been contained in one huge source file, so I decided to branch out and try putting my code in multiple files. I know that the proper way to do it is to have source files containing code definitions and such and a header file containing prototypes for other source files to use. This has worked out horribly for me and I either can't get the files to work together properly or it simply doesn't work period.
I have a single function in a source file called process.c and a function prototype in a file called process.h. I also have a main.h and a main.c containing all the rest of the code. The main issue is that I have a typedef struct Game in my main.h file and I can't get the 'Game' struct type I created to work in my process.c. Every function in my game needs the Game type in order to work. However, when I give process.c access to main.h (the file that Game is declared in) I get issues.
My code works fine when it's in one file. My header files are protected from duplication and are properly included in the program. The problem is, I need to include main.h in both main.c and process.c. And I have to include process.h in both 'main.c' and 'process.c'. I have tried every configuration and nothing works.
In some #include configurations I get no errors, but I get this weird message that says "It seems your project has not been built yet; would you like to build it now?" and when I click "Yes" nothing happens.
My compiler works fine and there is nothing wrong with the projects settings. What the heck is going on here? How do I get main.h and process.h to work together?
EDIT: Source code:
main.c:
#include <stdio.h>
#include "main.h"
#include "process.h"
void initGame(Game *thisGame)
{
variable = 10;
number = 5;
letter = 'c';
}
int main()
{
Game thisGame;
initGame(&thisGame);
displayData(&thisGame);
return 0;
}
main.h:
#ifndef _MAIN_H_
#define _MAIN_H_
typedef struct
{
int variable, number;
char letter;
}
#endif
process.c:
#include <stdio.h> //not sure if this should be here or not, it doesn't seem to effect my code
#include "main.h"
#include "process.h"
void displayData(Game *thisGame)
{
printf("%i, %i, %c", thisGame.variable, thisGame.number, thisGame.letter);
}
process.h:
#ifndef _MAIN_H_
#define _MAIN_H_
void displayData(Game *thisGame);
#endif
Error message
-------------- Build: Debug in FishKiller (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -L..\deps\lib -L..\SDLFILES\lib -o bin\Debug\FishKiller.exe obj\Debug\main.o obj\Debug\process.o -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
obj\Debug\process.o:process.c:(.rdata+0x0): multiple definition of `SCREEN_WIDTH'
obj\Debug\main.o:main.c:(.rdata+0x0): first defined here
obj\Debug\process.o:process.c:(.rdata+0x4): multiple definition of `SCREEN_HEIGHT'
obj\Debug\main.o:main.c:(.rdata+0x4): first defined here
obj\Debug\process.o:process.c:(.rdata+0x8): multiple definition of `GAMESTATE_MENU'
obj\Debug\main.o:main.c:(.rdata+0x8): first defined here
obj\Debug\process.o:process.c:(.rdata+0xc): multiple definition of `GAMESTATE_GAME'
obj\Debug\main.o:main.c:(.rdata+0xc): first defined here
obj\Debug\process.o:process.c:(.rdata+0x10): multiple definition of `GAMESTATE_GAMEOVER'
obj\Debug\main.o:main.c:(.rdata+0x10): first defined here
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
Issues are address file by file below. Once these issues are corrected in your source, the executable will build.
1)
In process.h you have the wrong header blocks:
#ifndef _MAIN_H_
#define _MAIN_H_
//Change to:
#ifndef _PROCESS_H_
#define _PROCESS_H_
Also change:
void displayData(Game *thisGame);(see notes in main.h for explanation)
To:
void displayData(GAME *thisGame);
2) In process.c you have;
#include "main.h"
It does not hurt anything, but since we are analyzing everything, it is not needed to support current architecture.
You also have:
printf("%i, %i, %c", thisGame.variable, thisGame.number, thisGame.letter);
Because the thisGame is passed in as a pointer, you need to use struct pointer operator: ->
printf("%i, %i, %c", thisGame->variable, thisGame->number, thisGame->letter);
Also, the function protocol in the same file is incorrect. You are attempting to instantiate a variable type that does not exist: (see notes for main.h)
Change:
void displayData(Game *thisGame){...}
To:
void displayData(GAME *thisGame){...}//uses typedef struct GAME
3) in main.h you have a malformed struct:
typedef struct
{
int variable, number;
char letter;
}//no ";" statement terminator to indicate to your compiler _end of struct_
And with this definition, there is no struct name with which to reference or instantiate it in any other file. Change it to the following:
typedef struct
{
int variable;
int number;//style point , put each member on its own line
char letter;
}GAME;//note struct type name and terminator ";"
With the struct type name, in this case GAME, you can create instances of this struct in any file that #includes this file.
extern GAME Game;// using the extern modifier, create an instance of GAME
// that can be referenced in any file of the
//project, once initialized. (See the line GAME Game; in main.c)
4) in main.c you have variables in the function initGame that need to be referenced differently. Change this:
void initGame(Game *thisGame)
{
variable = 10;
number = 5;
letter = 'c';
}
To:
void initGame(GAME *thisGame)
{
thisGame->variable = 10;
thisGame->number = 5;
thisGame->letter = 'c';
}
There is Code::Blocks information here that may help you to set up your environment to get the error messages that will help you to debug your code.
In the K&R book (p59) (edit: second edition, covering ANSI C), it is suggested that it is easier to split larger projects into multiple files. In each file, several libraries are included at the top as usual: e.g. getop.c needs stdio.h, and so does stack.c and so does main.c.
The snippets are something like this:
//main.c
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"
int main(void)
{
//etc
}
//getop.c
#include <stdio.h>
#include <ctype.h>
#include "calc.h"
getop()
{
/*code*/
}
//stack.c
#include <stdio.h>
#include "calc.h"
void push(double val)
{
//code
}
I am having trouble figuring out how including the standard libraries several times in a project works. Of course, for the custom .c files to be able to access built in functions, we need to include #include <header.h> so that they are aware of the existence of printf() and getchar() and so on, but wouldn't this approach increase the size of the final program if stdio.h is included four times instead of once ( if everything was placed in one file)?
K&R does point out that splitting a program over several files eventually makes it more difficult to maintain all the .h files.
I suppose what I am really asking is how does the compiler figure out the problem of one library being #included several times in a project.
I have read up on using include guards, but it seems that is not needed for this implementation, as they deal with ensuring that identical bits of code aren't included twice, as in:
File "module.h"
#ifndef MODULE_H
#define MODULE_H
struct foo {
int member;
};
#endif /* MODULE_H */
File "mod2.h"
#include "module.h"
File "prog.c"
#include "module.h"
#include "mod2.h"
refs
I suppose what I am really asking is how does the compiler figure out the problem of one library being #included several times in a project.
you don't include a library by #include <stdio.h>, you just include it's declarations, so the compiler knows what functions exists. The linker takes care of including a library and putting everything together.
Because they use something called include guards, suppose your own include files where to be included more than once, then you can do this
MyHeader.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
/* file content goes here */
#endif /* MY_HEADER_H */
Then you have another header
**AnotherHeader.h**
#ifndef MY_ANOTHER_HEADER_H
#define MY_ANOTHER_HEADER_H
#include "MyHeader.h"
/* file content goes here */
#endif /* MY_ANOTHER_HEADER_H */
and in your program
main.c
/*
* MY_HEADER_H is undefined so it will be defined and MyHeader.h contents
* will be included.
*/
#include "MyHeader.h"
/*
* MY_HEADER_H is defined now, so MyHeader.h contents will not be included
*/
#include "AnotherHeader.h"
int main()
{
return 0;
}
Since the included files are only included once per compilation unit the resulting binary size will not increase, besides the inclusion of header files only increases the compiled file size when for example there are string literals declared in those headers, otherwise they only provide information to the compiler about how to call a given function, i.e. how to pass parameters to it and how to store it's returned value.
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.