Configurations variables removed by compiler

216 views Asked by At

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.

3

There are 3 answers

6
ryyker On BEST ANSWER

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;
}
1
Enno On

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;
}
0
Mawg says reinstate Monica On

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.