Message Edited by CrasyCat on 2007-04-13 02:20 PM
I am still completely not getting this. What used to be easy in just creating a library file with extern blah and then including that library file in my main C program and being able to call that variable in all of my other C files, has turned into this L1818 duplicated in file1.c and file2.c
I have a file adc.h that has the following
//start of adc.h
#ifndef __adc
#define __adc
extern int state;
extern unsigned long adclow=0; // store a/d low 8 bits
extern unsigned long adchigh=0; // store a/d high 8 bits
extern unsigned long adcRTD=0; //store a/d RTD total in decimal
extern unsigned long adcR=0; //store a/d Resistance total in decimal
extern int RTD_Read_Times = 0;
extern float RTD1;
#endif
//end of adc.h
I have a file adc.c that has the following include
//start of adc.c
#include "adc.h"
float adc_to_tempC(int test) {
switch(state) {
case 0: break;
default : break;
}
}
//END of adc.c
I have a main.c file that has the following
#include "adc.h"
void main{
state++;
}
When I compile, it will tell me about all the duplicate extern variables that are in adc.h.
Link Error : L1818: Symbol 14 - adclow duplicated in adc.c.o and main.c.o
Link Error : L1818: Symbol 15 - adchigh duplicated in adc.c.o and main.c.o
Link Error : L1818: Symbol 16 - adcRTD duplicated in adc.c.o and main.c.o
Link Error : L1818: Symbol 17 - adcR duplicated in adc.c.o and main.c.o
Link Error : L1818: Symbol 18 - RTD_Read_Times duplicated in adc.c.o and main.c.o
Link Error : L1301: Cannot open file C:\my freescale projects\SetTime&Temp\Demo_Data\Standard\ObjectCode\adc.c.o
Link Error : Link failed
If I remove the #include adc.h from main, it will tell me it does not know what these variable are. Obviously the program I posted above has been lopped off so that I can show what I have here. I can assure you that in my main.c file, I do not have even 1 reference to adclow. I use the variable state as a switch for reading the ADC that is used in adc.c that I need to keep track of.
A declaration cannot have a initial value. If a variable has one, it is always a definition, even if there is a extern keyword.
So;
>extern unsigned long adclow=0;
is just the same as
>unsigned long adclow=0;
The header file should contain only:
// adc.h
>extern unsigned long adclow;
And in adc.h, the variable should be defined:
// adc.c
>#include "adc.h"
>unsigned long adclow=0;
This means that the variable is listed at two places, once as declaration in the header with extern and with no initialization value, and once as definition in the c file.
Daniel
You get the linker error because you are trying to initialize extern variables. Initialization must be done where the variable is actually declared (allocated).
---
Note the following:
- If you are using the ANSI option of Codewarrior, i.e. standard C, you don't need to initialize global variables to zero. All global variables are implicitly initialized to zero in the C language.
- It it considered bad programming to use global variables for many reasons. There are only two cases where you might need to declare global variables: When they are hardware registers, or when you have extreme demands on variable access time in performance-critical parts of a realtime system. In all other cases you shouldn't use extern/global variables, but instead use private encapsulation with set/get functions (that can be inlined).
- In embedded programming with systems that have non-volatile memory, you should avoid initialization of statics/globals entirely, because some non-standard compiler might remove initalization at startup to increase performance. Instead, set the variables in runtime before they are used.
This is how you want to handle the global variables of a module:
//file: SomeModule.h ---------------------#ifndef SOME_MODULE_H#define SOME_MODULE_H//declare public global variablesextern int SomeModule_Var1;extern int SomeModule_Var2;//declare public functionsvoid SomeModule_Init(void);#endif//file: SomeModule.c ---------------------#include "SomeModule.h"//define public global variablesint SomeModule_Var1;int SomeModule_Var2;//define private global variablesstatic int PrivateVar1;//declare private functionsvoid privateFunction(void);//implementation of public and private functionsvoid SomeModule_Init(void){ SomeModule_Var1 = 0; SomeModule_Var2 = 0; PrivateVar1 = 0;}void privateFunction(void){ PrivateVar1++;}//file: main.c ---------------------#include "SomeModule.h"void main(void){ SomeModule_Init(); SomeModule_Var1 = 3;}
Public global variables are declared (use extern) in header file. Public and private global variables are defined (do not use extern) in the c file. Everyone who wants to use your public variables and functions includes the header file. Remember that a #include statement merely replaces the statement with the text of the specified file.
bespenschied wrote:
From your summary, when does Global.c ever get used? and if I had a utilities.c file how would I Include the global declarations in it?
Message Edited by bigmac on 2006-06-07 04:11 PM
To really understand the way C documentation describes these things, you need to keep in mind the difference between a definition and a declaration.
A declaration just gives C just enough information to correctly reference a variable or function.
A definition creates a definite place for a C variable or function and completely describes it. It includes all the information in a declaration, but has the additional information of the variable initial value or a function body
A slightly different convention, which seems to give better documentation is to have the "globals.h" file of the form:
#ifndef __globals #define __globals// Global variables, declarationsexterm unsigned int Delay10ms;extern byte WaitTime;#endif //__globals
#include "globals'h"// Global variables, Actual definitionunsigned int Delay10ms = 10 ;byte WaitTime = 5 ;
Steve Russell wrote:A definition creates a definite place for a C variable or function and completely describes it. It includes all the information in a declaration, but has the additional information of the variable initial value or a function body
Regards,
Mac
bigmac wrote:
Hello Steve,
Steve Russell wrote:A definition creates a definite place for a C variable or function and completely describes it. It includes all the information in a declaration, but has the additional information of the variable initial value or a function body
So the difference between a declaration and a definition would seem to be a moot point for simple global variables that use implicit (default) initialisation to zero.Regards,
MacNot if you want a non-zero initial value.
My main point was that you will get extra confused when reading C specifications and discussions if you don't appreciate the difference between declaration and definition.
I confess, I don't remember exactly why the use of the implicit initialization is discouraged by some authorities.
Hello Steve,
I am still a little confused over the declaration/definition issue for global variables. Let's assume that we only have one file, say main.c. From your previous comments, I presume that the following code would be necessary, outside of any function, to declare/define a single global variable global_var1.
int global_var1; // Declaration?
int global_var1 = 0; // Definition?
void main(void)
{
etc.
Is this the correct interpretation of your previous explanation? Is it also allowable to combine the declaration and definition as a single assignment? Now I would assume that both the declaration and definition can only occur once in a program (there can only be a single initial value).
However, if we now add a second file that references the same global variable, I have previously understood that we need to tell the compiler to look for the declaration of the variable elsewhere. So the new file would need to include the following prior to first use of the variable, and this would occur for all additional files that use the variable:
extern int global_var1;
Is this correct? I am not sure whether this counts as a declaration, a definition, or something completely different.
Clarification of these simple cases would give a fuller understanding of more complex cases, such as global structures.
Regards,
Mac
Mac,
I'm sorry, I should have given some examples.
I was trying to give informal definitions of the terms. Look "declaration" and "definition" up in you favorite C book for different wording.
A declaration just gives C just enough information to correctly reference a variable or function.
As in:
Code:
extern int foo; // declaration double sin( double arg ) ; // declaration
The compiler gets enough information to reference the variable or function, but it is up to the linker to find where the actual variable or the function body is.
A definition creates a definite place for a C variable or function and completely describes it. It includes all the information in a declaration, but has the additional information of the variable initial value or a function body
Code:
int foo ; // definition tells compiler "put foo here"// definition tells compiler "put the sin function here,// with this definitiondouble sin( double arg ) { /* much code */} ;
Actually gives the storage location or the function body.
bigmac wrote:Hello Steve,
I am still a little confused over the declaration/definition issue for global variables. Let's assume that we only have one file, say main.c. From your previous comments, I presume that the following code would be necessary, outside of any function, to declare/define a single global variable global_var1.
int global_var1; // Declaration?
Actually a definition without an initializer given.
int global_var1 = 0; // Definition?
Yes, also a definition
void main(void)
{
etc.Is this the correct interpretation of your previous explanation? Is it also allowable to combine the declaration and definition as a single assignment?
You can't avoid it. A definition includes all the information in a declaration, and more
Now I would assume that both the declaration and definition can only occur once in a program (there can only be a single initial value).
Its good practice to have only one declaration for an item in a module, but many are allowed, if they all agree.
So, for example if you have a declaration for a function in a header file, it is helpful to include that header file in the module that defines the function. The compiler will report an error if the header file declaration doesn't match the definition.
You can only have one definition of something global in a program.
However, if we now add a second file that references the same global variable, I have previously understood that we need to tell the compiler to look for the declaration of the variable elsewhere. So the new file would need to include the following prior to first use of the variable, and this would occur for all additional files that use the variable:
extern int global_var1;
You are correct. This is indeed a declaration
One way to make handling of global variables easier is to use the following approach:
Code:
in globals.h#if ALLOC#define GLOBAL#else#define GLOBAL extern#endifGLOBAL char global_variable; GLOBAL int another_global_variable;
Code:
in main.c#define ALLOC 1#include "globals.h"
Code:
in the rest of the c-files#define ALLOC 0#include "globals.h"
Thanks for the help. I will read the document and try your suggestions. I also figured out that when you put constants like #define run 0 in the same header file as globals this causes problems because they are handled differently when compiled. I split the 2 up and now have a constants header file and a globals header file. It seemed to stop the errors I was getting.
Thanks!
Brian