It's clearly undefined as the declarations don't match. As you noted, const int
and int
aren't compatible types. A diagnostic is required only if they appear in the same scope.
It isn't safe in practice either, consider
$ cat test1.c
#include <stdio.h>
extern const int n;
void foo(void);
int main(void) {
printf("%d\n", n);
foo();
printf("%d\n", n);
}
$ cat test2.c
int n;
void foo(void) { ++n; }
$ gcc -std=c99 -pedantic test1.c test2.c && ./a.out
0
1
$ gcc -O1 -std=c99 -pedantic test1.c test2.c && ./a.out
0
0
Gcc assumes that n
isn't changed by foo()
when optimizing, because it may assume the definition of n
is of a compatible type, thus const
.
Chances are that you get the expected behaviour with also volatile
-qualifying n
in test1.c
, but as far as the C standard is concerned, this is still undefined.
The best way I can think of to prevent the user from accidentally modifying n
is to declare a pointer to const
, something along
int my_real_variable;
const int *const my_variable = &my_real_variable;
or perhaps some macro
#define my_variable (*(const int *)&my_variable)
With C99, my_real_variable
can be avoided via a compound literal:
const int *const my_variable_ptr = &(int){ 12 };
It would be legal to cast away const
here (as the int
object itself isn't const
), but the cast would be required, preventing accidental modification.