当定义不是const时,将extern全局视为const是否有效?

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吗?使用头文件设置它的最佳做法是什么?

maf*_*fso 5

由于声明不匹配,因此显然未定义.如您所述,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 ntest1.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),但是需要演员,防止意外修改.