Tom*_*vin 5 c standards standards-compliance c89
假设我有一个编译单元file1.c,它声明了一个文件范围变量,如下所示:
int my_variable = 12;
Run Code Online (Sandbox Code Playgroud)
然后,在另一个编译单元file2.c中,我为该变量创建了一个extern声明,但声明为const:
extern const int my_variable;
Run Code Online (Sandbox Code Playgroud)
这将使用gcc编译并正常工作-Wall -Wextra -ansi -pedantic.但是,C89标准规定要使两种合格类型兼容,两者都应具有相同类型的兼容类型.添加const到声明会增加限制而不是避免限制.这是安全有效的C吗?使用头文件设置它的最佳做法是什么?
由于声明不匹配,因此显然未定义.如您所述,const int并且int不兼容类型.仅当诊断出现在同一范围内时才需要诊断.
考虑到它在实践中也不安全
$ 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
Run Code Online (Sandbox Code Playgroud)
Gcc假设在优化时n没有改变foo(),因为它可能假设定义n是兼容类型,因此const.
有机会,你得到的也预期行为volatile-qualifying n中test1.c,但据C标准而言,这仍然是不确定的.
我能想到的防止用户意外修改的最好方法n是声明指向const某个东西的指针
int my_real_variable;
const int *const my_variable = &my_real_variable;
Run Code Online (Sandbox Code Playgroud)
或许是一些宏观
#define my_variable (*(const int *)&my_variable)
Run Code Online (Sandbox Code Playgroud)
使用C99,my_real_variable可以通过复合文字避免:
const int *const my_variable_ptr = &(int){ 12 };
Run Code Online (Sandbox Code Playgroud)
const在这里抛弃是合法的(因为int对象本身不是const),但是需要演员,防止意外修改.