0

I have a C program which has always used hard coded define statements for a few settings. Example...

#define TRIGGER_TIMEOUT 50000

This has worked just fine. Now, this setting is to become adjustable. Example...

g_ulTriggerTimeout = ReadEEPROM(TRIGGER_TIMEOUT_OFFSET);

If persistent storage is detected (EEPROM) then the value will be read in and used. So, my safe literal value is now at risk of being corrupted (inadvertently written changed). I need to make this variable a constant, however I also need to read in the initial values from EEPROM. How is this scenario typically solved?

Jason
  • 201
  • 3
  • 11

3 Answers3

1

I do not like bending the rules (invoking undefinded behaviour) like RedX's answer does. Therefore, I now give a C standard-compliant solution. The price is having a constant function instead of a constant variable.

int g_ulTriggerTimeout()
{
    static int done; // statically initialized to zero
    static int value;
    if( !done )
    {
        value = haveEEPROM ? ReadEEPROM(TRIGGER_TIMEOUT_OFFSET)
                                      : TRIGGER_TIMEOUT;
        done = 1;
    }
    return value;
}

Following is my first answer, it is however only valid in C++:

const int g_ulTriggerTimeout = haveEEPROM ? ReadEEPROM(TRIGGER_TIMEOUT_OFFSET)
                                          : TRIGGER_TIMEOUT;
Community
  • 1
  • 1
Peter G.
  • 14,786
  • 7
  • 57
  • 75
  • This does not help against accidental modification of `g_ulTriggerTimeout` later in the program. – undur_gongor Apr 03 '12 at 13:26
  • @undur_gongor, ok, let me add a `const` – Peter G. Apr 03 '12 at 13:28
  • It is probably embedded development and dev there seem to like spaghetti code + declaring far away from first assignment (i'm an embedded dev). So it is likely the assignment and declaration are not in the same line. Plus the var is probably global. – RedX Apr 03 '12 at 13:32
  • @RedX My example is out of context but if it appeared at global scope it would define a global constant. Also, if the OP wants a solution, he can forgo spaghettis and just use this simple constant definition. – Peter G. Apr 03 '12 at 13:40
  • The initialization of a "global" variable has to be a constant value. You cannot call functions then. – undur_gongor Apr 03 '12 at 13:48
1

This is IMHO one of those cases where bending the rules is ok.

const int g_ulTriggerTimeout; //declare somewhere making sure it is in a writable section (see comment below from undur)

/* later */

//just for this assignment make it modifiable
*((int*) &g_ulTriggerTimeout) = ReadEEPROM(TRIGGER_TIMEOUT_OFFSET);
RedX
  • 14,749
  • 1
  • 53
  • 76
  • This is not portable. I'd even guess this will not work on most platforms. – undur_gongor Apr 03 '12 at 13:34
  • @undur_gongor Why is this not portable? Note i just fixed it to take the adress of `g_ul...` – RedX Apr 03 '12 at 13:38
  • I too would like to know why this is not portable? I prefer this solution because (right or wrong) I typically place my globals at the top of the .c file and all of my persistent settings are loaded in one function call (GetSettings()). – Jason Apr 03 '12 at 13:43
  • "If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined." (ISO/IEC 9899:1999, 6.7.3, §5). E.g. the variable could be put into a ROM area. – undur_gongor Apr 03 '12 at 13:46
  • @undur_gongor That is correct. But probably (since he must be modifying it in a function, this is c) it is not in any read-only area as ATM it is not `const` qualified. But i will take your note to consideration and update my answer. – RedX Apr 03 '12 at 13:48
  • Then it is still UB (although it will most probably work). See http://stackoverflow.com/questions/8051969/c-accessing-a-non-const-through-const-declaration for details. – undur_gongor Apr 03 '12 at 13:52
0

You cannot (portably/with C).

If you have to modify the variable in your program (by reading it from EEPROM), you cannot lock it against modification by your program.

There might be platform specific means to achieve that though.

undur_gongor
  • 15,657
  • 5
  • 63
  • 75