Can const variables be modified from elsewhere not known at compile time - c

If const is a compile time construct, it would mean that only the compiler will ensure that for example if a variable is declared as const, this variable is read only and it is not attempted to be modified by the rest of the code being compiled?
What about if a const variable is a global variable in our code, and our code links to a dynamic library at run time which attempts to write to it? , or if an ISR attempts to update it, which was not in our compiled code?
I believe the compiler can mark const variables to be loaded into the read only data section which would prevent any changing of the variable, but what if it doesn't?
Thanks

the compiler will ensure that for example if a variable is declared as const, this variable is read only and it is not attempted to be modified by the rest of the code being compiled?
Yes, as far as the compiler is able to tell. If your code attempts to write to a const-qualified variable, you will get a compiler error. If you dodge type correctness by for example casting away the const qualifier, then all bets are off.
What about if a const variable is a global variable in our code, and our code links to a dynamic library at run time which attempts to write to it? , or if an ISR attempts to update it, which was not in our compiled code?
Then it should not have been const qualified, or the compiler will make strange assumptions and generate incorrect code.
However, there exist cases where a const variable may be updated from the outside world - it could be a read-only hardware register or an EEPROM memory cell etc.
To prevent the compiler from doing strange assumptions in such special cases, you can then combine const and volatile. All variables that may be updated from an external source, such as hardware or an ISR, should therefore always be declared as volatile.

Related

Volatile is not preventing a variable from being optimized

As I know, "volatile" keyword is used to prevent compiler to optimize an unused variable. I am working with an STM32 board and I declare and initialise a variable as follows;
volatile uint32_t errorCallbackCounter = 24 ;
And never use it again.
While debugging, this variable is not seen. I am checking it with STMStudio( a real time variable watcher ) and when I want to import variables, the adress of errorCallbackCounter is seen as 0x0.
But when I use it in anywhere, it becomes visible.
So volatile keyword is not doing its job or -more probably- I know something wrong about it.
Thanks in advance.
Variables that are never used can be dropped by the linker
The volatile keyword affects the code that accesses the variable, preventing the access from being rearranged or dropped by the compiler. The line above is a variable definition with an initializer, that doesn't count as an access, it gets arranged before main() starts. But if it isn't referenced by accessible program code, isn't accessed at all, the linker thinks that it's safe to remove it, no one would notice.
You can however mark the variable as "it's needed no matter what" with
__attribute__((used))
placed at the end of the definition. This works with gcc, other compilers might have another directive for it. There is also a linker option that I can't recall right now to include all unused data sections in the executable.
volatile means the system will load this variable from memory each time it is accessed.
The compiler is not allowed to store the data directly into an register.
The volatile keyword prevents the compiler from performing optimization on code involving volatile objects, thus ensuring that each volatile variable assignment and read has a corresponding memory access. Without the volatile keyword, the compiler knows a variable does not need to be reread from memory at each use, because there should not be any writes to its memory location from any other thread or process.

C: Using static volatile with "getter" function and interruptions

Suppose I have the following C code:
/* clock.c */
#include "clock.h"
static volatile uint32_t clock_ticks;
uint32_t get_clock_ticks(void)
{
return clock_ticks;
}
void clock_tick(void)
{
clock_ticks++;
}
Now I am calling clock_tick (i.e.: incrementing clock_ticks variable) within an interruption, while calling get_clock_ticks() from the main() function (i.e.: outside the interruption).
My understanding is that clock_ticks should be declared as volatile as otherwise the compiler could optimize its access and make main() think the value has not changed (while it actually changed from the interruption).
I wonder if using the get_clock_ticks(void) function there, instead of accessing the variable directly form main() (i.e.: not declaring it as static) can actually force the compiler to load the variable from memory even if it was not declared as volatile.
I wonder this as someone told me this could be happening. Is it true? Under which conditions? Should I always use volatile anyway no matters if I use a "getter" function?
A getter function doesn't help in any way here over using volatile.
Assume the compiler sees you've just fetched the value two lines above and not changed it since then.
If it's a good optimizing compiler, I would expect it to see the function call has no side effect simply optimize out the function call.
If get_clock_ticks() would be external (i.e. in a separate module), matters are different (maybe that's what you remember).
Something that can change its value outside normal program flow (e.g. in an ISR), should always be declared volatile.
Don't forget that even if you currently compile the code declaring get_clock_ticks and the code using it as separate modules, perhaps one day you will use link-time or cross-module optimisation. Keep the "volatile" even though you are using a getter function - it will do no harm to the code generation in this case, and makes the code correct.
One thing you have not mentioned is the bit size of the processor. If it is not capable of reading a 32-bit value in a single operation, then your get_clock_ticks() will sometimes fail as the reads are not atomic.

Is a C compiler obligated to always reload const value from memory?

I have a const variable in my embedded C program. It's defined and initialized with 0 in program code. It's placed in a special ROM area via linker script. One can change the content of the special area via special programming procedure, but it cannot be changed during main program execution.
The question is whether I have to declare the constant as volatile. If it's not marked as volatile, is the compiler allowed to replace all references to it with 0? Or is it obligated to load it at least once during program execution?
It looks like your variable is really a constant (i.e. doesn't change during program execution) with a value unknown to the compiler. If this is the case, you can declare it like this:
extern const int variable;
(i.e. without volatile and without an initializer) and let the linker script or other tools set up the correct value.
The compiler will then be permitted to load it and potentially leave it in a register forever, but not replace it by 0 or any other value at compile time.
If marked as volatile the compiler is obliged to load it from memory every time it needs it value.
If not marked as volatile, the compiler may load it once from memory, store it in a register, and use this register instead of loading it again.
A not-optimizing compiler may do this - but it also may, stupidly, load it every time. (As not reloading is in fact an optimization in itself.)
Optimizing compilers may notice the const and decide it can be compiled with its real, literal value; up to a point where the original constant does not appear at all in the .data section of your program. (Or maybe it does but it never gets "read".)
Since you change the value in a linker script, the compiler cannot "know" the value got changed after compiling. In that case, use volatile: the only way to tell the compiler not to trust that the value is known when compiling.

'const' in C language may be redundant?

I have been confusing with const in the C language. I think if no const conception, all the programme existed in the world also could run smoothly.so Can anyone help me and give me some explanation.
Yes, if you removed const, most1 C code would continue to work as it does today.
However, const really exists to save the programmer from himself. The const modifier on a function parameter says: "this function promises to not modify the object this points to." So if you forget, and try to modify the object, the compiler will stop you.
1 - I say "most" because const can also have a runtime effect. Statically-allocated objects marked const will typically be placed in a read-only section in the program image, and this data is marked as read-only when the program is loaded. So if you were to cast away the const and try to write to this object, your program will segfault. The crash here is desired. Because it prevents your program from running with invalid assumptions about its data.
No, is not redundant at all. The qualifier const is usually applied to the declaration of any variable to specify that its value will not be changed during the program execution (Which depends upon where const variables are stored, we may change value of const variable by using pointer). If you have ever programmed in Java, is similar to an static variable.
You can read more about const here: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
const will make the assembly code into an absolute number value. It will not be a register or memory value and can't be modified by the code of course. It makes for fast program operation because it doesn't load the value from memory or a register.
However, most optimized coding already does this in assembly when it realizes the value isn't changed.
John

ROM variable not getting the defined value

I'm working on developing a software stack for automotives based on a Renesas RL78 controller. Getting straight into the problem, variables declared const(ROM variables) are not getting initialized with the defined value.
Ex : const uint8 var_test = 1;
On the other hand, global,static variables are getting initialized.
Is this the problem with the startup code? kindly suggest...
Like the other answers, probably your const variable isn't placed into a ROM section.
You need to tell the compiler/linker where to place it.
With an IAR toolchain it's probably something like
#pragma SET_CONST_PAGE(ConstArea)
const int myVariable1=42;
const int myVariable2=4711;
#pragma SET_DEFAULT_CONST_PAGE
But that your debugger doesn't show the correct value is another problem, it's possible that the variable is optimized.
To be sure what happens look into the map file and look (with the debugger) at assembly level what is done.
Usually const isn't enough of a qualifier to allow variables to go in ROM (you could always cast it away). Usually you need to mark the variable with something compiler specific to indicate what you want, or perhaps a compiler flag to indicate your intention. I believe the IAR compiler uses the # symbol to allow you to specify a location for a variable. I'd check its manual :-)
Non-static const variables are not "constant enough" to go into ROM, typically. If you inspect a function using such variables, you'll probably see that the function's preamble has code to initialize the variables on the local stack.
Of course, startup code can't fix this, since it (by definition) can't write the values into ROM.
Const objects are not required by the language to be located in ROM, but merely to be read-only after initialisation, and for reasons of performance on some targets for example a compiler might deliberatly avoid doing so.
The IAR RL78 C/C++ Compiler Reference Guide states :
"Static and global objects declared const and located in far memory are allocated in
ROM. const declared saddr objects are allocated in RAM and initialized by the runtime
system at startup. const declared near objects are allocated according to the option
--near_const_location.
In C++, objects that require runtime initialization cannot be placed in ROM."
Refer to the #pragma location directive or the # operator in the manual, these allow placement at absolute addresses or within named memory segments.

Resources