I had a project based on a single C file that I try to rearrange for further development in several .c and .h files.
My main is organised as follow:
// General includes
typedef struct
{
} MyStruct;
#include "MyInclude.h"
// Rest of the code
My file "MyInclude.c" is organised as follow:
#include "MyInclude.h"
// Defines
// Functions that need to know MyStruct
There is something I don't understant about the compilation process of GCC. In fact, I got the error "MyStruct undeclared (first use in this function)" and I don't why as I put my include after the typedef declaration of my structure.
Does someone knows why it happens?
The question is a bit unclear.
The file "MyInclude.c" can access only to your H file.
While your struct is written in another C file.
You can solve it by:
Define the struct on the H file "MyInclude.h". It will work, but methodologically it's wrong.
Define setters and getters to access your struct
Cheers
Your file.h :
// file.h
#include <stdio.h> //Juste for printf
typedef struct s_data
{
char c;
} t_data;
Your file.c :
#include "file.h"
int main()
{
t_data data;
data.c = 'a';
printf("%c", data.c);
return (0);
}
Compil (if your file .c and .h are in the same directory):
gcc file.c -o my_app -I .
Related
I creating a program in c language and i using the Visual Studio Code for the first time, my functions in the header files don't function. This is my code in main:
#include <stdio.h>
#include "PilhaDinamica.h"
#include "PilhaEstatica.h"
int main()
{
Pilha *p = criaPilha();
return 0;
}
And this is my .h file:
#ifndef PILHADINAMICA_H_INCLUDED
#define PILHADINAMICA_H_INCLUDED
typedef struct Nodo{
char info;
struct Nodo*prox;
} nodo;
typedef struct {
nodo * Topo;
} Pilha;
Pilha * criaPilha();
int pilha_vazia(Pilha *p);
void push(Pilha *p, char times);
char pop(Pilha *p);
#endif
This is my file with the functions:
#include "PilhaDinamica.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Pilha *criaPilha()
{
Pilha *p = (Pilha*) malloc(sizeof(Pilha));
p->Topo = NULL;
return p;
}
And this is shown in my output: "...\AppData\Local\Temp\ccmjk1nS.o:main.c:(.text+0xf): undefined reference to `criaPilha'
collect2.exe: error: ld returned 1 exit status"
what can i do to make it compile correctly?
As a general rule of thumb, header files (*.h) contains declarations (type, variable and function declarations) and source files (*.c) the definitions of those declarations.
At the compilation step, only source files will be compiled (because the definitions are there). A program or library creation is a 2 (actually more, like preprocessing and more but for simplicity we keep it at 2) step process:
creating object files
e.g. gcc -c -o object_file_name.o source_file_name.c
link those object files into an executable or static/shared library
e.g. gcc -o program_or_library_name object_file_1.o object_file_2.o ...
So, in your case you have to call the compiler two times for your source files (with the -c flag) and once to link those created object files into an executable.
Note: If you're using a different compiler other than gcc, have a look at the documentation on how to create object files and link them together.
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.
I am building a project that I am trying to organize as follows:
main.c
globals.h
structures.h
FunctionSet1.c, FunctionSet1.h
FunctionSet2.c, FunctionSet2.h
etc.
I thought I could define a structure type in structures.h:
struct type_struct1 {int a,b;}; // define type 'struct type_struct1'
then declare a function1() returning a structure of type type_struct1 in FunctionSet1.h:
#include "structures.h"
struct type_struct1 function1(); // declare function1() that returns a type 'struct type_struct1'
then write function1() in FunctionSet1.c:
#include "FunctionSet1.h"
struct type_struct1 function1() {
struct type_struct1 struct1; // declare struct1 as type 'struct type_struct1'
struct1.a=1;
struct1.b=2;
return struct1;
}
Edit: with the corrected code above, the compiler returns
306 'struct' tag redefined 'type_struct1' structures.h
Is the file set good practice ?
What is the good practice to manage the structures ?
In your example, you declare a structure named type_struct in structure.h, then in FunctionSet1.h the structure that you are returning is type_struct, and in the .c it is called struct1.
So i think that the problem is that struct1 and type_struct are not recognized because they have never been defined ...
However, the organization of your files is fine.
Your general structure looks good. One thing you need to do, as zenith mentioned, is to put include guards into your header files. What that is is a set of #define's that make sure that the contents of the header are not included more that once in a given file. For example:
structures.h:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct type_struct1{
int a,b;
};
...
// more structs
...
#endif
FunctionSet1.h:
#ifndef FUNCTION_SET_1_H
#define FUNCTION_SET_1_H
#include "structures.h"
struct type_struct1 function1();
...
// more functions in FucntionSet1.c
...
#endif
main.c:
#inlcude <stdio.h>
#include "structures.h"
#include "FunctionSet1.h"
int main(void)
{
struct type_struct1 struct1;
struct1 = function1();
return 0;
}
Here, main.c includes structures.h and FunctionSet1.h, but FunctionSet1.h also includes structures.h. Without the include guards, the contents of structures.h would appear twice in the resulting file after the preprocesser is done. This is probably why you're getting the "tag redefined" error.
The include guards prevent these type of errors from happening. Then you don't have to worry about whether or not a particular header file was included or not. This is particularly important if you're writing a library, where other users may not know the relationship between your header files.
First of all, you have to declare the structure in your file.h (you can use typedef to create an alias)
typedef struct Books
{
char title[50];
int book_id;
} books;
then, you have to include your file.h in your file.c and declare your variable like this
#include "file.h"
int main()
{
books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
or like this if you didn't use typedef
#include "file.h"
int main()
{
struct Books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
Thank you all.
I read again what you said and found that the code above is now correct.
The error I report is with testing the following main.c
#include "structures.h"
#include "FunctionSet1.h"
void main() {
struct type_struct1 struct2;
struct2=function1();
}
in which structures.h is included again, thus causing the error. Removing the include eliminates the error.
I will now look into header guards to avoid such problems.
Thanks again.
I have a confusion about external structs. I have to define a global instance of the struct in a file other than which the struct is defined (as a RAM variable which I do not know what it is exactly).
Below is an example that GCC can compile and it runs correct while Code Composer Studio gives compile-time errors.
I want to learn where the problem is, how GCC can compile, and where/how I should use the extern declaration.
Any comment would be appreciated.
person.h
#ifndef PERSON_H
#define PERSON_H
struct person {
int age;
};
typedef struct person PERSON;
void modifyPerson();
#endif // PERSON_H
personRam.h
#ifndef PERSONRAM_H
#define PERSONRAM_H
#include "person.h"
PERSON p1;
#endif // PERSONRAM_H
modifyPerson.c
#include "person.h"
#include "personRam.h"
void modifyPerson() {
p1.age = 10;
}
main.c
#include <stdio.h>
#include "person.h"
#include "personRam.h"
int main() {
modifyPerson();
printf("%d", p1.age);
return 0;
}
You should not get a compiler error, but a linker error, saying that p1 is defined multiple times. At least that's what I guess is the problem.
The reason is that you define the variable in a header file, which you then include in multiple source files. This means that the definition is in both source files (The preprocessor #include directive literally puts the contents of the header file in place of the include "statement").
If you declare the variable as extern in the header file, and define it in one source file it should work.
So in personRam.h
extern PERSON p1;
And in one of the source files:
PERSON p1;
On which operating system are you compiling, and for which target system?
For what it is worth, Linux (& Unix-es) and Windows have different linking semantics.
Read Levine's "Linkers & Loaders" book for details.
I am using Linux as my programming platform and C language as my programming language.
My problem is, I define a structure in my main source file( main.c):
struct test_st
{
int state;
int status;
};
So I want this structure to use in my other source file(e.g. othersrc.). Is it possible to use this structure in another source file without putting this structure in a header?
You can define the struct in each source file, then declare the instance variable once as a global, and once as an extern:
// File1.c
struct test_st
{
int state;
int status;
};
struct test_st g_test;
// File2.c
struct test_st
{
int state;
int status;
};
extern struct test_st g_test;
The linker will then do the magic, both source file will point to the same variable.
However, duplicating a definition in multiple source files is a bad coding practice, because in case of changes you have to manually change each definition.
The easy solution is to put the definition in an header file, and then include it in all the source file that use the structure. To access the same instance of the struct across the source files, you can still use the extern method.
// Definition.h
struct test_st
{
int state;
int status;
};
// File1.c
#include "Definition.h"
struct test_st g_test;
// File2.c
#include "Definition.h"
extern struct test_st g_test;
You can use pointers to it in othersrc.c without including it:
othersrc.c:
struct foo
{
struct test_st *p;
};
but otherwise you need to somehow include the structure definition. A good way is to define it in main.h, and include that in both .c files.
main.h:
struct test_st
{
int state;
int status;
};
main.c:
#include "main.h"
othersrc.c:
#include "main.h"
Of course, you can probably find a better name than main.h
// use a header file. It's the right thing to do. Why not learn correctly?
//in a "defines.h" file:
//----------------------
typedef struct
{
int state;
int status;
} TEST_ST;
//in your main.cpp file:
//----------------------
#include "defines.h"
TEST_ST test_st;
test_st.state = 1;
test_st.status = 2;
//in your other.ccp file:
#include "defines.h"
extern TEST_ST test_st;
printf ("Struct == %d, %d\n", test_st.state, test_st.status);
Putting it in a header file is the normal, correct way to declare types shared between source files.
Barring that, you can treat main.c as a header file and include it in the other file, then only compile the other file. Or you can declare the same struct in both files and leave a note to yourself to change it in both places.
C supports separate compilation.
Put the structure declaration in a header file and #include "..." it in the source files.
It is perfectly reasonable to be inclusive with structs by leaving them in the source file instead. This is encapsulation. However if you're going to redefine struct multiple times in multiple source files then you might as well define the struct once in a header file instead and include that file as necessary.
Header file /* include this header file in both file1.c and file2.c
struct a {
};
struct b {
};
so header file included the declaration of both structures .
file 1.c
struct a xyz[10]; --> struct a defined here
to use struct b here in this file
extern struct b abc[20];
/* now can use in this file */
file2.c
struct b abc[20]; /* defined here */
to use struct a defined in file1.c
use extern struct a xyz[10]