Is it valid to declare in my headers a const variable, but define it as a non-const variable for internal use?
-
Just asking ;) why would you do that ? – limserhane Jan 06 '21 at 22:45
-
1Have you tried it to see what happens? – Diaco Jan 06 '21 at 22:45
-
Does this answer your question? [Is it legal C to declare a non-const variable 'const' externally?](https://stackoverflow.com/questions/63525933/is-it-legal-c-to-declare-a-non-const-variable-const-externally) – Nate Eldredge Jan 07 '21 at 01:08
-
@NateEldredge yes, thank you – John Friendson Jan 07 '21 at 01:27
3 Answers
The only logical way of declaring variables in the header file is to declare them as extern
As #include
only inserts the text of the header file into the source code file (https://godbolt.org/z/nor8nz) you can simply test you idea in the single source file:
extern const int x;
int x;
You will get the error:
1
ARM gcc 8.2
- 347ms
<source>:4:5: error: conflicting type qualifiers for 'x'
int x;
^
<source>:2:18: note: previous declaration of 'x' was here
extern const int x;
^
Compiler returned: 1

- 60,014
- 4
- 34
- 74
No, this causes undefined behavior.
C17 6.6.7 (2):
All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
6.7.3 (11):
For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
Since const
is a qualifier, types such as int
and const int
are not compatible, and therefore it is undefined behavior to have both an int
and a const int
declaration of the same object. (And the definition of the object is itself a declaration, so it counts.)
One of many possible undesired consequences, in practice, could be that in source files (translation units) that have a const
declaration, the compiler may assume that the variable is actually constant, and may fail to notice if it is modified. For example, code like the following:
#include <stdio.h>
extern const int x;
void bar(void);
void foo(void) {
printf("%d\n", x);
bar();
printf("%d\n", x);
}
may cache the value of x
in a callee-saved register across the call to bar()
, and so will always print the same value twice. See on godbolt. This would happen even if another file contains
int x = 5;
void bar(void) {
x = 6;
}

- 48,811
- 6
- 54
- 82
I hope for better answers that can address the direct question about the validity.
But this is almost certainly a bad approach. My suggestion is to use a function that returns the value instead. Another option would be to use a pointer to const. Something like:
int x;
int *const ptr = &x;
Using globals the way you describe is dangerous territory. If I ever would like to do something like that, I'd probably just accept that I have to be really careful.
One might be tempted to use a pointer like this:
const int x;
int *ptr = &x; // Bad, bad idea
But do NOT try to do that, as it invokes undefined behavior. Source: Can we change the value of an object defined with const through pointers?

- 30,332
- 17
- 55
- 95