I have a number of modules in a C program for a microcontroller not running any OS. Each module has its own type definitions, enumerations, and data structre definitions to represent the module's status and I think it would be neat to define them in the module's associated header file.
Then, I have a global variable defined in global_var.c to "remember" the current status of the whole system. Since the modules' data structures are being referred to in the global variable's definition, all the module headers are being included in global_var.h.
However, these modules will also need to access the global variable thus they will need to include global_var.h as well.
How can I avoid mutual inclusion of the header files if I really want to keep my global variable?
Many thanks!
global_var.h
#ifndef GLOBAL_VAR_H
#define GLOBAL_VAR_H
#include "module.h"
typedef struct GLOBAL_STRUCTURE {
module_structure m;
} global_structure;
#endif
global_var.c
#include "global_var.h"
global_structure gs;
module.h
#ifndef MODULE_H
#define MODULE_H
typedef struct MODULE_STRUCTURE {
int a;
} module_structure;
void module_function(void);
#endif
module.c
#include "global_var.h"
extern global_structure gs;
void module_function(void) {
gs.m.a=0;
}
I think the C language is supposed to share a global defined twice. but it depends on the compiler (well linker) as to whether your toolchain actually does that I have had some that do and some that dont. The safest route is to only declare the variable once and everywhere else explicitly declare it as extern. You will often see this done like this:
common.h
#ifundef HELLO
#define HELLO
#endif
HELLO unsigned int myglobx;
one.c
#include "common.h"
two.c
#include "common.h"
three.c
#define HELLO extern
#include "common.h"
Try this:
In Module.c
#define XYZ
then in Module.h
#define MODULETYPE
#ifdef XYZ
MODULETYPE
#else
MODULETYPE extern
#endif
MODULETYPE int var1,var2;
Do this for every module and include your header wherever you want.
Related
I'm trying to figure out, how to use C headers with #ifndef and #include.
Lets say I have these two header files:
headerA.h:
#ifndef HEADERA_H
#define HEADERA_H
#include "headerB.h"
typedef int MyInt;
TFoo foo;
... some other structures from headerB.h ...
#endif
headerB.h
#ifndef HEADERB_H
#define HEADERB_H
#include "headerA.h"
typedef struct foo{
MyInt x;
} TFoo;
#endif
headerA.c
#include "headerA.h"
... some code ...
headerB.c
#include "headerB.h"
... some code ...
When compiling headerB.c, it says
In file included from headerB.h,
from headerB.c:
headerA.h: error: unknown type name ‘MyInt’
I think, it's becouse when headerB.h is compiling, it defines HEADERB_H and then, when headerA.h wants to include headerB.h, the #ifndef HEADERA_H is false = skips including.
What is the best practice here? I just read, that best practice is to do all #include directives in header files, but in this situation it looks like a problem.
EDIT: Ok, sorry for misleading you. This is just and example from bigger project with more files.
You have a circular dependency. Header file headerA.h depends on headerB.h which depends on headerA.h and so on and on.
You need to break that dependency, for example by not including headerB.h in headerA.h. It's not needed (nothing in headerA.h needs anything from headerB.h).
If you have to include headerB.h (as stated in your recent edit) then you first should reconsider how you use your header files, and what definition you place where. Perhaps move the definition of MyInt to headerB.h? Or have more header files, like one for type-aliases (like your MyInt which I personally see no use for), one for structures and one for variable declarations?
If that's not possible then you could try by changing the order of definitions and the include, like
#ifndef HEADERA_H
#define HEADERA_H
// Define type alias first, and other things needed by headerB.h
typedef int MyInt;
// Then include the header file needing the above definitions
#include "headerB.h"
TFoo foo;
... some other structures from headerB.h ...
#endif
Just drop the line
#include "headerB.h"
from file headerA.h
I have defined an enum in a header file,
global.h:
Typedef enum
{
ELEMENT1,
ELEMENT2,
ELEMENT3
}e_element;
I have a second file using the enum as a function parameter.
file2.c
#include global.h
#include file2.h
Function(e_element x)
{
Body…
}
The prototype is in:
file2.h
Function(e_element x);
The compiler doesn’t know e_element in file2.h. I have tried putting the #include for global.h in both file2.c and file2.h, but it still doesn’t see it. I would put the enum in file2.h, except that it is used by several other files, so if I move it the problem will just show up somewhere else.
How can I get the file2.h prototype to see e_element?
This worked for me:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
typedef enum
{
ELEMENT1,
ELEMENT2,
ELEMENT3
}e_element;
#endif
file2.h
#ifndef FILE_2_H
#define FILE_2_H
#include "global.h"
int test(e_element);
#endif
file2.c
#include "file2.h"
int test(e_element x)
{
return x == ELEMENT1;
}
int main() {
return 0;
}
edit:
#ifndef is conventionally used as a "header guard". It prevents a header file from being included multiple times by the preprocessor, which prevents things from being defined multiple times. It works by checking if a unique symbol has been defined before. If it has not, then it immediately defines it and then continues with the header file until #endif. If the symbol was already defined then it skips the guarded code completely, preventing multiple definitions. An example of multiple definitions would be if the same header file was included in a source and a header that the source also includes.
See this link for more information.
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.
So I have a header file let's say "header.h" which is protected as follows:
#ifndef __HEADER1_H
#define __HEADER1_H
//type and function def
typedef struct
{
float r; //process noise
float k; //process gain
}state_t;
int get_state(state_t* state, float b);
#endif
Now I have two other headers which I defined as follows:
#ifdef __HEADER2_H
#include "header.h"
//function def
#endif
Second header:
#ifdef __HEADER3_H
//function
//the reason it is done this way is for cnditional compiling such that if the caller
//defines __HEADER3_H t this file won't be included.
#include "header.h"
#endif
Now as I suspected the compiler complained that types and functions defined in header.h were not detected in the source implementation of header2 and header3. So I included header.h in the source files as well. Now the linker is complaining functions that are defined in header.h are multiply defined.
My understanding was since the header.h is protected by ifndef it will only be included once so I don't see the problem.
here is the error that I am getting:
Symbol get_state multiply defined(by kalman.o and dsp.o)
Is there any chance that I am doing something unusally wrong?
#ifndef __HEADER1_H
#define __HEADER_H
The problem is your guard (__HEADER_H) is different from what you are checking for (__HEADER1_H). Make these both the same value.
The typical "guard" for a header file is:
myheader.h:
#ifndef _MYHEADER
#define _MYHEADER
<do stuff>
#endif
Optionally where myheader.h is included, you can do:
#ifndef _MYHEADER
#include "myheader.h"
#endif
This is optional and basically is only to improve compile performance.
I have to turn back to (embedded) C after some lengthy time with C++, and have the following problem:
I have a source module which is included a lot of times, let's call it utilities.h and utilities.c
In it, I have an important array, let's call it
#define IMPORTANT_ARRAY_LENGTH 10000
char important_array[IMPORTANT_ARRAY_LENGTH];
I have a lot of other functions in this utilities module, and they all work fine. However, in one of the other source files, let's call it worker.c, I have to use this array. What is the "official", elegant way to do this, without having to put extern char important_array[IMPORTANT_ARRAY_LENGTH] and the macro definition in the worker.c ?
If I do the following:
utilities.h
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
#define IMPORTANT_ARRAY_LENGTH 10000
extern char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
utilities.c
#ifndef _UTILITIES_C_
#define _UTILITIES_C_
#include "utilities.h"
char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
worker.c
#include "utilities.h"
// ...
important_array[0] = 0;
then my array will be an undefined symbol in worker.c. If I don't use the extern keyword in utilities.h, then of course, it's a duplicate symbol. (Strangely, it compiles with just a warning, and I can see from the linker file that the size is allocated multiple times.)
Do I really have to declare my array in worker.c? I want to keep everything clean, and have all declarations in one place only: in a header file. And I want to have the macro definition only once (this is secondary, because I could use a const, but I want the preprocessor to handle it, and not take up place)
What you have is the canonical way to do it: have an extern declaration in the header file, and define the variable in the .c file.
my array will be an undefined symbol in worker.c
No, it won't. Your code will compile and link just fine.
I often put the definition in the header (this is frowned upon, I know).
It keeps the definition and declaration close together, which is a Good Thing.
/* file.c */
#define FILE_C 1
#include "file.h"
.
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#define BIG_SIZE 13
#if FILE_C
char the_array[BIG_SIZE];
#else
extern char the_array[BIG_SIZE];
#endif
#endif /* FlLE_H */
.
/* other_file.c */
#include "file.h"
There is no risk of doing it wrong: the linker will complain if you do it wrong.
BTW a similar way to basically do the same, but maybe a bit more readable, is:
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#if FILE_C
#define EXTERN /**/
#else
#define EXTERN extern
#endif
#define BIG_SIZE 13
EXTERN char the_array[BIG_SIZE];
...
#undef EXTERN
#endif /* FlLE_H */
Having one declaration (extern...) in each translation unit and exactly one definition is the most elegant way to do this.
So leave the extern char important_array in the header and char important_array in one of the .c files.
Create a new function at utilities.c called something like "get_important_array" that just returns a pointer to array and put the prototype at utilities.h. After that, when you put the utilities.h at worker.c you'll have important_array access in a simple, and organized way.