In my header file file.h I have:
#ifdef FILE_H
extern "C" {
#endif
int size;
int array[3];
void saveToFile();
void loadFromFile();
#ifdef FILE_H
}
#endif
After I try compiling it, table with "Source file not compiled" pops up and I also get warning like this command line option '-std=c99' is valid for C/ObjC but not for C++.
In my file.c I have:
#include <stdio.h>
#include <stdlib.h>
#include "file.h"
void saveToFile(){
FILE *load=fopen("1uzd.txt", "w");
int array[3];
fprintf(load, "%d ", 3);
array[0]=1;
array[1]=2;
array[2]=3;
for(int i=0; i<3; i++){
fprintf(load, "%d ", array[i]);
}
fclose(load);
}
void loadFromFile(){
FILE *load=fopen("1uzd.txt", "r");
int size;
fscanf(load, "%d", &size);
int array[size];
for(int i=0; i<size; i++){
fscanf(load, "%d", &array[i]);
}
printf("%d %d %d", size, array[0], array[1]);
}
And undefined reference to `WinMain' with ld returned 1 exit status
And in main.c:
#include <stdlib.h>
#include <stdio.h>
#include "file.h"
int main(void){
saveToFile();
loadFromFile();
return 0;
}
With undefined reference to saveToFile', undefined reference to loadFromFile' and ld returned 1 exit status.
In my header file file.h I have:
#ifdef FILE_H
extern "C" {
#endif
int size;
int array[3];
void saveToFile();
void loadFromFile();
#ifdef FILE_H
}
#endif
Your multi-inclusion guards have the wrong sense and scope. Also, if your intention is for this header to be usable in both C and C++, then the extern "C" declaration is incorrectly protected. Perhaps you want this:
#ifndef FILE_H
#define FILE_H
#ifdef __cplusplus
extern "C" {
#endif
int size;
int array[3];
void saveToFile();
void loadFromFile();
#ifdef __cplusplus
}
#endif
#endif
That provides for
the contents of the header to be considered only the first time the header is included in any translation unit, and
the extern "C" declaration to be ignored unless the header is being processed by a C++ compiler.
After I try compiling it, table with "Source file not compiled" pops
up and I also get warning like this command line option '-std=c99' is
valid for C/ObjC but not for C++.
One does not compile headers directly. One uses #include directives to incorporate their contents into other sources. The source files you present contain such #include directives, so you should not need to do anything further in that regard.
In my file.c I have [...] undefined reference to `WinMain'
You are trying to compile file.c as a complete program, but that doesn't work because it does not have a main() function.
And in main.c [...] undefined reference to saveToFile', undefined reference to loadFromFile'
You are trying to compile main.c as a complete program, but it does not contain the source of a complete program because it calls functions that are defined in a different source file.
There are two main approaches you could take:
compile each .c file to an object file and then link them together into a whole program in a separate step, or
compile both .c files in a single compilation command.
Details of both options depend on the compiler and build system used. Some of your diagnostic messages suggest GCC to me, and with GCC running in command-line mode, the latter would be something like
gcc -std=c99 -o my_program.exe main.c file.c
. The "my_program.exe" is the name you want your executable to have. The -std=c99 is necessary with your code for some versions of GCC, and the diagnostics suggest that it appears in the command-line arguments you are actually using. You may include other command-line options, too, if you wish.
Note also that you must use a C compiler to compile C code, not a C++ compiler. Your diagnostics suggest that you may be trying to use the latter. C and C++ are different languages. Although they have a shared subset, neither is a superset of the other.
Related
so i create the object files with
cc -c MAIN.C
cc -c tablero.c
but then when i try to link them to an executable with
cc MAIN.o tablero.o
i get
undefined reference to `asdf()'
(function defined in tablero.c and called in MAIN.C)
here are my files:
i have MAIN.C
#include <stdio.h>
#include <cstring>
#include "tablero.h"
int main()
{
int c;
printf( "Enter a value :");
c = getchar( );
putchar(c);
printf( "\nYou entered: ");
c = asdf ();
putchar(c);
return 0;
}
i have tablero.h
#ifndef TABLERO_H_
#define TABLERO_H_
int asdf();
#endif // TABLERO_H_
and i have tablero.c
#include "tablero.h"
int asdf() {return 48;}; //48 is 0 in ascii
You have been bitten by an obscure feature of the cc tool on many Unixy systems: files whose suffix is lowercase .c are compiled as C, but files whose suffix is uppercase .C are compiled as C++! Therefore, your main (compiled as C++) contains an external reference to a mangled function name, asdf() (aka _Z4asdfv), but tablero.o (compiled as C) defines only an unmangled name, asdf.
This is also why you were able to include the C++ header file <cstring> in what was meant to be a C program.
Rename MAIN.C to main.c (and change <cstring> to <string.h>), recompile main.o, and your program should link.
If you actually want to compile part of your program as C and part as C++, then you can annotate your header files with extern "C" to make the symbols match up:
#ifndef TABLERO_H_
#define TABLERO_H_
#ifdef __cplusplus
extern "C" {
#endif
int asdf(void);
#ifdef __cplusplus
}
#endif
#endif // TABLERO_H_
Header files like this have to be extra careful to contain only code that has the same meaning in C and C++. Only POD types, no C++ keywords, no C99-but-not-C++ keywords either, no overloads, et cetera.
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.
This is my header file, tree.h
#ifndef TREE_H_
#define TREE_H_
#if defined treeItem
extern int totalnode;
treeItem *addItem(treeItem *node, char *w);
void printInOrder(treeItem *node, FILE *output);
void freeTree(treeItem *node);
#endif
#endif
This is the main() in main.c which include tree.h
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "tree.h"
#define MAX 1024
extern int totalnode;
int main(int argc, char *argv[]){
FILE *input;
FILE *output;
char *filename;
char ch[MAX];
//extern int totalnode;
struct treeItem *element;
element = NULL;
int i;
if (argc > 2){
output = fopen(argv[1], "w");
for(i = 2; i < argc + 1; i++){
filename = argv[i];
input = fopen(filename, "r");
if(input != NULL){
while(getword(ch, MAX, input) != EOF)
if (isalpha(ch[0]))
element = addItem(element, ch);
}
}
printInOrder(element, output);
fprintf(output,"-------------- \n ");
fprintf(output,"%4d Total number of different words",totalnode);
freeTree(element);
fclose(input);
fclose(output);
}
else{
printf("There is no input file.\n");
}
return 0;
}
compiler says:
../main.c: In function 'main':
../main.c:57: warning: implicit declaration of function 'addItem'
../main.c:57: warning: assignment makes pointer from integer without a cast
../main.c:60: warning: implicit declaration of function 'printInOrder'
../main.c:64: warning: implicit declaration of function 'freeTree'
another error: Undefined symbols for architecture x86_64:
"_totalnode", referenced from:
_main in main.o
_addItem in tree.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
If I put all code in the same .c file without using header file, it works. But for now, it doesn't work. How can I fix it?
The line
#if defined treeItem
and the matching #endif should be removed from tree.h
Remember that preprocessing occurs conceptually before (or as the very first step of) the real compilation.
In general, you could have obtained the preprocessed form of main.c with
gcc -C -E main.c > main.i
and then look (e.g. with a pager like less) inside main.i
I often remove the generated preprocessor directives with
gcc -C -E main.c | grep -v '^#' > main.i
gcc -Wall -c main.i
this gives error messages with line numbers referring inside main.i (not main.c or tree.h) which is sometimes useful to debug macros. Another useful option to gcc is -H: it shows every #include-d file
In order to use the tree.h file 'as-is', and have it define items as you expect, you will have to define treeItem:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
/* You will need to define 'treeItem' prior to including 'tree.h'. */
typedef /* the defintition here */ treeItem;
#include "tree.h"
#define MAX 1024
extern int totalnode;
If you have the liberty of editing the tree.h file, it would probably be better to remove the line:
#if defined treeItem
and one of the lines:
#endif
Because you have pre compiler directives which exclude the substantive body of tree.h unless treeItem is defined, you must #define treeItem prior to the inclusion of tree.h within main.c, this is due to the way that precompiler directives are processed. This will solve the immediate problem.
I see that in main.c you have the line: struct treeItem *element;
If I am interpreting correctly that you intended this to satisfy the #ifdef treeItem line in your header, then you are misunderstanding how these # lines are like a separate language to C/C++. These lines are called precompiler directives, or more casually macros. Macros are commands for the preprocesser which operates over text files prior to compilation, for the purposes of creating in memory a full source code that can be compiled into an object that can later be linked with others to form your program. The preprocessor's defines are different from definitions in C/C++, and they don't directly interact. This line about the struct is practically invisible to the preprocessor, it knows nothing about C/C++. You must define this treeItem using #define, prior to the #ifdef.
More aesthetically, your header file should not guard like this, because it is superfluous. The main.c module's #include "tree.h" line alone is enough to indicate the intention of including the substantive body of tree.h. You have an appropriate guard against repeated inclusions, but the second guard regarding the treeItem definition seems unnecessary and is the cause of this issue. This latter paragraph is simply reiterating what other's have said, and would be technically superfluous as well if it does not contribute to persuading you of this opinion, however avoiding hypocrisy the first paragraph is a solution to your issue that does not intrude on your decision regarding said opinion.
I am currently working on my first "serious" C project, a 16-bit vm. When I split up the files form one big source file into multiple source files, the linker (whether invoked through clang, gcc, cc, or ld) spits out a the error:
ld: duplicate symbol _registers in register.o and main.o for inferred
architecture x86_64
There is no declaration of registers anywhere in the main file. It is a uint16_t array if that helps. I am on Mac OS 10.7.3 using the built in compilers (not GNU gcc). Any help?
It sounds like you've defined a variable in a header then included that in two different source files.
First you have to understand the distinction between declaring something (declaring that it exists somewhere) and defining it (actually creating it). Let's say you have the following files:
header.h:
void printIt(void); // a declaration.
int xyzzy; // a definition.
main.c:
#include "header.h"
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
When you compile the C programs, each of the resultant object files will get a variable called xyzzy since you effectively defined it in both by including the header. That means when the linker tries to combine the two objects, it runs into a problem with multiple definitions.
The solution is to declare things in header files and define them in C files, such as with:
header.h:
void printIt(void); // a declaration.
extern int xyzzy; // a declaration.
main.c:
#include "header.h"
int xyzzy; // a definition.
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
That way, other.c knows that xyzzy exists, but only main.c creates it.
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.