Header variable turn to zero - c

I am using STM32F103 and and Keil for the Compiler. Here is my summary code:
There is a header file like abc.h and abc file has a static variable. abc.h is like that:
static uint8 a;
And there is a function in another header file which named abcd.h and that changes the a' s value.
abcd.h header file is like that.
include "abc.h"
void foo()
{
a = 0x0A;
}
My issue is that:
When I call the "foo" fuction in main "a" is turn to zero even if I assign the "a" variable to 0x0A in "foo()" function. By the way, If I define the "a" variable with extern and the problem does not occured. I mean "a" is get 0x0A value.
Is there anyone the help me why does this problem occur.

Some rules of thumb:
Never declare global variables. (extern ones)
Never declare variables inside header files.
static variables are per definition not global, but could be "file scope" - that is, visible to the file they are declared inside. Or more accurately, visible inside the translation unit they are declared inside, a translation unit meaning a specific .c file and all the headers that .c file includes.
So if you declare a static variable in a header, which is included by two different .c files, then you end up with multiple local copies of the variable. If you are lucky, you get a linker error, but the linker may as well attempt some internal "name mangling". The very meaning of static is to prevent access to the variable by other files.
The best solution to this is to use setter/getter functions:
// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H
uint8_t get_a (void);
void set_a (uint8_t n);
#endif
-
// abc.c
#include "abc.h"
static uint8_t a;
uint8_t get_a (void)
{
return a;
}
void set_a (uint8_t n)
{
a = n;
}
That is how you should be doing in the vast majority of cases. Using extern should be avoided, but for the rare cases when you have to use it, then use it like this:
// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H
extern uint8_t a;
#endif
-
// abc.c
#include "abc.h"
uint8_t a;

Related

Configurations variables removed by compiler

I am attempting to define a set of global variables which will configure my device, about 10 in a dedicated .c file, that will be changed on a regular basis at compile time (as per device requirements), I want these to be in this separate file so they can all be changed easily. These variables are then called throughout my program in various files. And are never changed only read. The problem is that my compiler (XC8 for PIC MCU's) doesn't define the variable, as it can only see that one use of the variable in the file, even though it is called with extern throughout the program.
config.h
unsigned int Global_A;
unsigned int Global_B;
void config(void);
config.c
void config(void)
{
unsigned int Global_A=987;
unsigned int Global_B=123;
}
prog_a.h
extern unsigned int Global_A;
extern unsigned int Global_B;
unsigned int var_A;
void prog_a(void);
prog_a.c
unsigned int var_A=0;
void prog_a(void);
{
var_A=Global_A+Global_B;
}
main.c
#include config.h
#include prog_a.h
void main(void)
{
while(1)
{
config();
prog_a();
}
}
as a result, the equivalent var_A is always 0, as the compiler has done away with config.c as it cannot see the variable called again.
I'm assuming the answer is very obvious to those more versed, but I can't find anything online. I have not had any trouble with using extern and globals before when they are used in the file the are defined in. But I could just be using it wrong fundamentally, so feel free to berate me.
Thanks in advance.
p.s if it wasn't obvious this is an example code to illustrate my problem.
Your function config declares two new variables in the scope of the function (their names hide those of the global variables). They don't exist anywhere outside of it, and assigning a value to them does nothing. If your goal was for it to initialize the globals, you need do this:
// config.h
extern unsigned int Global_A;
extern unsigned int Global_B;
void config(void);
// config.c
unsigned int Global_A;
unsigned int Global_B;
void config(void) {
Global_A=987;
Global_B=123;
}
With extern keyword it it necessary to declare the variable once (preferably in a header file) define it once in a .c file that has visibility to the declaration statement. That is it. Where the extern defined variable is necessary, #include the header file in which the declaration statement occurred.
Also note it is important also to define extern variable(s) in global scope (i.e. not in a function).
config.h:
#include "prog_a.h"
//unsigned int Global_A;
//unsigned int Global_B;
void config(void);
main.c
#include config.h
#include prog_a.h
...
//suggest defining these here:
unsigned int Global_A=0;//define outside of function
unsigned int Global_B=0;
...
config.c
#include "prog_a.h"
...
void config(void)
{
Global_A=987;
Global_B=123;
}
Your global variables are all of type int, so why not just use #define?
Change file config.h to
#define Global_A 789
#define Global_B 123
You do not actually have to declare any int variables to hold those values, plus, they will be const and unmodifiable.
That's they way that we did it "back in the day", but in the last decade or two, I see more and more actually storing these configuration values in an external text file
It can be a .INI, or XML or JSON, etc, etc, that is up to you.
You just create different files, let's say Singapore.ini and Paris.ini and Auckland.ini, etc, each containing a key/value pair.
e.g
time_zone = X
population = Y
etc, etc
Then, at the start of your main, read the file in and store the values -but not in globals, which are frowned upon, these days. Read them into variables which are local to config.c, and have config.c/h provode methods to read their values, e.g GetTimeZone() and GetPoulation(), etc
Don't worry about any code size or run time impact of this, as any decent compiler will in-line these function calls.
One advantage to reading "global" configuration values in an external text file is that you only need to build your software once. You do not need to rebuild and have an executable for each configuration, which the road that you are currently heading down.
Firstly, this makes it easier to test your software (especially automated test), by merely editing the text file, or supplying a new one.
Also, since you only have a single executable, you can ship that to all of your users/customers, and give each a tailored config file. You can totally control & change the functionality of your software just by changing the config file. You might want to think about that.

static function declarations in header files

I have a static function in a source file that is used by other functions in that same source file. Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files? Example:
/* foo.c */
#include "foo.h"
/* exported function; calls g */
void f(void) {
g();
}
static
void g(void) {
/* do something... */
}
/* foo.h */
void f(void);
void g(void);
/* main.c */
#include "foo.h"
int main(void) {
f();
}
Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files?
No. Consider the conflict the other source files would have if they had a function/object/macro of the same name.
Even without conflict, an "unused function" warning may occur. #Adrian Mole
By putting static void g(void) in the .h file, it adds an unnecessary potential name conflict.
Simply declare/define that static function at the top of the .c in which it is used.
Is it fine to put the declaration for that static function in the
header file, even though that header file will be included into other
source files?
No. becuse it does not make any sense. and why?
In C, functions are global by default. Unlike global functions in C, access to static functions is restricted to the file where they are declared! Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be reuse of the same function name in other files. so declaring them static in the header file can cause to name collisons in other source files.
In header files we declare our API functions those we want to expose only. in c files we declare usually auxilary functions as static functions for restricting the scope of those aux functions to the c file only

Globals declared in h file and access to them

Just a simple question for understanding:
variable extern int x_glob is declared in header glob.h.
so in every c file that contains functions declared in glob.h using this variable I have to define it agin like this:
extern void func_1( void )
{
int x_glob;
glob_x++;
return();
}
Is that correct?
If I leave off the extern word on the declaration of x_glob in glob.h, I don't need the definition.
Why not leaving away the extern word in the header file?
Maybe this question sounds stupid - my goal is to get a better structure into
my programming as the projects grow.
No, this is wrong. With int x_glob inside a function you declare a local, automatic variable. This overrides any global variable.
But in precisely one .c file you must declare the global variable:
// main.c
int x_glob;
This creates one variable that can now be used by all modules. The extern version of the variable only tells the compiler when compiling the other modules that somewhere there exists this variable and it will be found upon linking the modules into the excutable.
Personally I prefer the following set-up:
// glob.h
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN int x_glob;
// module.c
#include "glob.h"
// main.c
#define EXTERN
#include "glob.h"
In all modules x_glob will be known as extern and in main it will not be extern and so will declare the storage for the global variable.

C - extern, static, include

Scoping in C is confusing as hell. I have a variable: "int qwe". This var should be visible in one or more files - f1.c in this case, but not the another f2.c .
Say i have: main.c, f1.c, f2.c, header.h
main:
call f1();
call f2();
header:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
int qwe = 1;
void f1();
void f2();
#endif // HEADER_INCLUDED
f1.c:
#include <stdio.h>
extern int qwe;
void f1(){
printf("In f1: %d\n", qwe);
}
f2.c:
#include <stdio.h>
static int qwe = 2;
void f2(){
printf("In f2: %d\n", qwe);
}
Now this gets confusing. There is definition and declaration. I have defined qwe in the header, declared it in f1.c. Is that correct? Should definition happen in header and declaration in f1.c instead? I tried the latter case, but got an error - "multiple definition of qwe". When i removed the #include directive from f1.c, it worked... It also works when i remove the extern keyword. Is extern redundant?
f2.c i guess it's ok and behaves as expected, or is it? But if i put an #include with header, it breaks. Why is that?
When should i use #include in source files? If i don't include it f1.c or f2.c it works...
Also, if i define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data. And next time that same function gets called, will have access to it, right? But the var won't be reinitialized to 0, i.e. the line where is defines won't execute. Correct?
Life stomps me :(
In the header, declare the variable. In e.g f1.c, define the variable, e.g. int qwe = 1; // at global scope.
In all files that want to see/change qwe, include the header that declares the variable. Easy-peasy.
You need to declare the variable in the header, and define it in one and only one C file.
In C, you cannot have a variable that doesn't "belong" to a given translation unit (source file). So it must be defined by exactly one translation unit in the whole program.
When you declare a variable as extern, you're telling the compiler the symbol is (possibly) external to your translation unit (c file).
It's probably also worth noting that when you try to declare a variable without extern, the variable is also defined, e.g.:
/* Declares, but does not defines external symbol 'foo' */
extern int foo;
/* Both declares AND defines bar */
int bar;
This is also different from how functions work to where the "default" syntax for declaration does NOT define a function:
/* Declare, but don't define spam */
void spam(void);
/* Declare, but don't define eggs */
extern void eggs(void);
/* Declare & define 'cheese' */
void cheese(void){ return; }
So your example should look more like this:
qwe.h:
#ifndef QWE_H
#define QWE_H
/* Declare qwe here */
extern int qwe;
#endif
f1.c:
/* DEFINE qwe here */
int qwe = 1;
f2.c:
#include "qwe.h" /*header includes the `extern int qwe` declaration */
void my_function(void)
{
/* use external symbol here! */
qwe = 10;
}
The scoping system isn't that confusing. The rule is this:
if you define something in a .c file EVERY other .c file in your program can access it (it is put in the global namespace).
if you specify static in front of its definition then only things in the SAME file can see it. This should be your default position for all functions and variables you don't want other .c files to be able to access.
It is very important to remember that extern only tells the compiler that the variable/function in question is not defined in the current file. This prevents the compiler for otherwise issuing an error because it can't find the symbol, but it has nothing to do with scoping - your .c file sees everything in the global namespace and if you have not followed the second part of the rule you will quickly find out about this at link time.
Header files similarly have nothing to do with scoping. They are just convenient places to put a bunch of extern statements and macros.
In C, you should use the header file in general to declare the data but not define the data. You don't want to define global data in a header because it will then be redundantly defined in multiple modules. The header indicates to multiple modules the existence of some data or function somewhere and what its type is, as well as common constants and macros (#defines). Outside of that, things in C are very simple. Just about anything is, technically, global unless you declare it static, keeping it scoped to the module it's defined in. The extern declarations for data in the headers and the function prototypes help the compiler know that these items are being accessed by a particular module and what the data types are for access so that the correct code can be generated.
You have:
Two functions f1 and f2 that are defined in separate modules but used in main. So these need to be declared in a header file.
A global data item qwe being used in more than one module.
A static qwe used in one module.
Assuming you want this done with one header file (you might need separate ones for f1, f2, and global data - see below), you could set up
your header as:
#ifndef MY_HEADER_H
#define MY_HEADER_H
extern int qwe;
void f1(void);
void f2(void);
#endif // MY_HEADER_H
Then in your main.c:
...
#include "my_header.h"
int qwe; // This is global and can be accessed from other modules
void main(...)
{
// call f1
// call f2
...
I just defined the global variable, qwe, in main.c arbitrarily. If you have a few globals, you can define them in their own glob_data.c module, for example, and have it's own header, glob_data.h, to declare them. Any other module that needs to access them would include the glob_data.h header so that compilation can properly be done on that module to access that data. Keeping the global data in separate headers helps with cases like you have where you have a static instance of the data versus the global, which are in conflict. You can avoid including the data header file for that global item when you want to compile with the static item.
Then in your C file, f1.c:
...system headers included...
#include "my_header.h"
void f1() {
printf("In f1: %d\n", qwe);
}
And in f2.c:
...system headers included...
#include "my_header.h" // Only if it doesn't contain `extern int qwe;`
static int qwe = 2; // This hides the global qwe and is known only
// to f2.c
void f2(){
printf("In f2: %d\n", qwe);
}
As I mentioned above, you might want to separate your function prototypes and your global data declaration in separate headers. That way, you can include only what's needed in each module and avoid conflicts, such as when you have a static int qwe; versus the global int qwe;.
I have defined qwe in the header, declared it in f1.c. Is that correct?
No, it should be the other way around. You are supposed to have a definition of a global variable in a single translation unit (that's geek speak for a .C file) but you may declare it in as many translation units as you wish. Since headers potentially get included from many translation units, declarations go in the headers.
When should i use #include in source files?
You do it when the header has anything that is needed for your translation unit to compile, with very few exceptions. Note that in some situations it may be necessary or desirable to make a forward declaration manually without including the header.
Also, if I define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data.
That is correct, the static variable inside the function will be assigned the initial value only once, and retain the value that you assign to it for as long as your program continues to run.

How to make global variable in library project using MPLAB X IDE

I want to create a library in C using MPLAB X IDE(ide for PIC developing).
My library ABCLib has one simple source file like this:
file abc.c
void abcTest(int n){
// I want store n as global variable
}
To using this library in MyProject i have to create abc.h inside MyProject header folder:
file abc.h
#ifndef _ABC_H
#define _ABC_H
void abcTest(int n);
#endif;
file MyProject.c(main file)
#include "abc.h"
void main(void) {
abcTest(10);
}
Now, i want to store n as global variable, so, after a call to abcTest() i can retrieve the value of n whereever i want.
I'm developing a library with intention to reuse it in all my projects.
You'll need to declare the variable as external in all files you want to use his global value.
Example:
file abc.c
extern int global_a;
void abcTest(int n){
global_a+=n;
}
file abc.h
#ifndef _ABC_H
#define _ABC_H
void abcTest(int n);
#endif;
file MyProject.c(main file)
#include "abc.h"
int global_a = 0; // always initialize global variables
void main(void) {
abcTest(10);
}
Regards
After compiling the MyProject.c, the abc.h file will be included in the translation unit, so a global static variable should remain visible within that translation unit. In order to access it from external objects you'll have to have a function in the translation unit that can pass the value to the outside.
Otherwise just name it anywhere in your file without scope, it will be global. In order to have a global carry across multiple files, use the extern keyword to tell the compiler that you're referring to a global variable already existent in another linker symbol.

Resources