我可以在公共标头中而不是在私有标头中将变量声明为const吗?

Mat*_*att 4 c linker const header-files

例如,我可以做这样的事情,以便只能foo.c修改变量foo吗?:

foo.h:

extern const int foo;
void foo_init(void);
void foo_reinit(void);
Run Code Online (Sandbox Code Playgroud)

foo.private.h:

int foo;
void foo_init(void);
void foo_reinit(void);
Run Code Online (Sandbox Code Playgroud)

foo.c:

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

bar.c:

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

因此,以下将产生错误/警告:

baz.c:

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

这保证正确链接吗?

R..*_*R.. 5

不可以.如果声明不匹配,程序的行为是不确定的.特别是,由于使用公共头的翻译单元声明对象是const合格的,编译器在翻译它们时可以假设指向的数据永远不会改变,因此它可以将值缓存到外部调用功能,包括改变它的功能.

如果您只是想要防止意外编写试图修改数据的代码,请执行以下操作:

extern int foo;
#define foo (*(const int *)&foo)
Run Code Online (Sandbox Code Playgroud)

然后,您可以#undef foo在实际允许更改它的模块中.


oua*_*uah 5

我可以在公共标头中而不是在私有标头中将变量声明为const吗?

不,你不能因为它调用未定义的行为.

(C11,6.2.7p2)"所有引用相同对象或函数的声明都应具有兼容类型;否则,行为未定义."

const int并且int是两种类型不兼容的类型.

(C11,6.7.3p10)"对于两个要兼容的限定类型,两者都应具有相同类型的兼容类型;说明符或限定符列表中类型限定符的顺序不会影响指定的类型"