我可以在 public header 中而不是在私有 header 中将变量声明为 const 吗?
Can I declare a variable as const in the public header and not in the private header?
例如,我可以做这样的事情,只有foo.c
可以修改变量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;
}
这样下面的语句就会产生一个 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;
}
这保证 link 正确吗?
你喜欢踩多薄的冰?
是的,你可以做到。你会侥幸逃脱的。但该标准并不能保证您的代码会按预期工作。相同的 object 应在所有地方一致声明。
但是主要的问题是你失去了你应该需要的 cross-checking 因为你的 'private' 代码应该使用 public header 来确保声明外部使用匹配实现。也就是说,foo.c
应该有 #include "foo.h"
以确保告知消费者使用的内容与实现提供的内容相匹配(在 foo.c
中)。如果你不这样做,事情迟早会出问题。
此外,请记住编译器讨厌被骗。当你对他们撒谎时,他们会想办法报复他们。你的代码对编译器说谎了。
没有。如果声明不匹配,则程序的行为是未定义的。特别是,由于使用 public header 的翻译单元声明 object 是 const
合格的,编译器在翻译它们时可以假设 object =19=] 数据永远不会改变,所以它可以在调用外部函数时缓存值,包括改变它的函数。
如果您只想防止意外编写试图修改数据的代码,请执行以下操作:
extern int foo;
#define foo (*(const int *)&foo)
那你可以#undef foo
在实际允许的模块里改
我可以在 public header 而不是在私有 header 中将变量声明为 const 吗?
不,你不能,因为它会调用未定义的行为。
(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
和 int
是两种类型不兼容的类型。
(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"
不,你不能,但据我了解你的代码,你可以将 foo
设为静态,作为函数 foo_init
和 foo_reinit
,并公开一个简单的 get_foo
到其他模块。
例如,我可以做这样的事情,只有foo.c
可以修改变量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;
}
这样下面的语句就会产生一个 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;
}
这保证 link 正确吗?
你喜欢踩多薄的冰?
是的,你可以做到。你会侥幸逃脱的。但该标准并不能保证您的代码会按预期工作。相同的 object 应在所有地方一致声明。
但是主要的问题是你失去了你应该需要的 cross-checking 因为你的 'private' 代码应该使用 public header 来确保声明外部使用匹配实现。也就是说,foo.c
应该有 #include "foo.h"
以确保告知消费者使用的内容与实现提供的内容相匹配(在 foo.c
中)。如果你不这样做,事情迟早会出问题。
此外,请记住编译器讨厌被骗。当你对他们撒谎时,他们会想办法报复他们。你的代码对编译器说谎了。
没有。如果声明不匹配,则程序的行为是未定义的。特别是,由于使用 public header 的翻译单元声明 object 是 const
合格的,编译器在翻译它们时可以假设 object =19=] 数据永远不会改变,所以它可以在调用外部函数时缓存值,包括改变它的函数。
如果您只想防止意外编写试图修改数据的代码,请执行以下操作:
extern int foo;
#define foo (*(const int *)&foo)
那你可以#undef foo
在实际允许的模块里改
我可以在 public header 而不是在私有 header 中将变量声明为 const 吗?
不,你不能,因为它会调用未定义的行为。
(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
和 int
是两种类型不兼容的类型。
(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"
不,你不能,但据我了解你的代码,你可以将 foo
设为静态,作为函数 foo_init
和 foo_reinit
,并公开一个简单的 get_foo
到其他模块。