…you can never go back.
After being shown that you can declare a global variable, as one does…
int g_globalVariable;
…and then make it be treated as a read-only variable to other files by extern-ing it as a const:
extern int const g_globalVariable;
…of course I wondered what the compiler did if you went the other way:
// main.c
#include <stdio.h>
void function (void);
int const c_Value = 0;
int main()
{
printf("Hello World\n");
printf ("c_Value: %d\n", c_Value);
function ();
printf ("c_Value: %d\n", c_Value);
return 0;
}
// function.c
#include <stdio.h>
// Extern as a non-const.
extern int c_Value;
void function ()
{
c_Value++;
}
Above, main.c contains a global const variable, but function.c tries to extern it as non-const.
But when I run the code…
Hello World
c_Value: 0
...Program finished with exit code 139
Press ENTER to exit console.
…the compiler does not complain, but we get a crash. Looking at this in a debugger shows more detail:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551ef in function () at Function.c:11
11 c_Value++;
I am unfamiliar with the inner workings on whatever compiler this Online C Compiler – online editor is using, but I suspect I’d see similar results doing this on any system with memory protection. Go back to the early days (like OS-9 on a 6809 computer, or even on a 68000 without an MMU) and … maybe it just allows it and it modifies something it shouldn’t?
We can file this away in the “don’t do this” category.
Until next time…
By declaring it “const”, you tell the compiler it can live in the “rodata” (read only data) section of the binary, or even the “text” (program code) section. On modern systems, these will be mapped into memory as read only so writing to it triggers the protection fault. On systems without memory protection, it will just modify the value (or, if you have your program in ROM, try to modify and nothing happens).
Basically, it’s a runtime error triggered by the hardware. The compiler has no idea the original definition of c_Value is constant when it builds function.c so it cannot flag an error there. The linker has no idea what symbols are being used for so it cannot flag a reference error (the linker basically just has a bucket of bytes with some symbol definitions and reference locations). That leaves it for the program loader to mark read only things as read only where hardware support exists and the hardware to enforce it.
Is the pre processor where the error comes from?