Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I declare a variable as const in the public header and not in the private header?

For example, can I do something like this so that only foo.c can modify the variable foo?:

foo.h:

extern const int foo;
void foo_init(void);
void foo_reinit(void);

foo.private.h:

int foo;
void foo_init(void);
void foo_reinit(void);

foo.c:

#include "foo.private.h"
void foo_init() { foo = 1; /* ... */ }
void foo_reinit() { foo++; /* ... */ }

bar.c:

#include <foo.h>
int main()
{
    foo_init(); printf("foo: %d\n", foo);
    foo_reinit(); printf("foo: %d\n", foo);
    return 0;
}

And so that the following would produce an error/warning:

baz.c:

#include <foo.h>
int main()
{
    foo_init(); printf("foo: %d\n", foo);
    foo = 0; /* ERROR/WARNING for modifying const variable */
    return 0;
}

Is this guaranteed to link correctly?

like image 719
Matt Avatar asked Dec 12 '22 01:12

Matt


2 Answers

Can I declare a variable as const in the public header and not in the private header?

No, you cannot as it invokes undefined behavior.

(C11, 6.2.7p2) "All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined."

const int and int are two type incompatible types.

(C11, 6.7.3p10) "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"

like image 84
ouah Avatar answered Dec 28 '22 09:12

ouah


No. If the declarations mismatch, the behavior of the program is undefined. In particular, since the translation units using the public header are declaring that the object is const qualified, the compiler can, when translating them, make an assumption that the pointed-to data will never change, so it could cache the value across calls to external functions, including the functions that change it.

If you just want protection against accidentally writing code that tries to modify the data, do this:

extern int foo;
#define foo (*(const int *)&foo)

Then you can #undef foo in the modules that are actually permitted to change it.

like image 24
R.. GitHub STOP HELPING ICE Avatar answered Dec 28 '22 07:12

R.. GitHub STOP HELPING ICE