问题描述
我正在检查具有不同链接的声明中可能发生的各种情况,我有两个问题。
I。我有以下代码:
@Override
public void onViewCreated(@NonNull final View view,@Nullable Bundle savedInstanceState) {
RecyclerView recyclerView = findViewById(R.id.list);
// recyclerView is not null now
}
可以与#include <stdio.h>
static int a = 19;
int main(void)
{
extern int a;
{
extern int a;
printf("braces - %d\n",a);
}
printf("main - %d\n",a);
}
和clang
一起很好地编译,并且在两个gcc
中都打印出19
的相同结果。据我所知,根据标准6.2.2。,4),所有pritf
都是a
。我唯一不了解的是,为什么static
的文件作用域a
在主括号和大括号中可见?是否不应该按照脚注31隐藏文件范围?当我在其他文件中用不同的值定义另一个a
时,两个a
的输出仍为19。
II。现在,我执行以下操作:
printf
#include <stdio.h>
static int a = 19;
int main(void)
{
int a; //change in this line
{
extern int a;
printf("braces - %d\n",a);
}
大喊gcc
,而variable previously declared ‘static’ redeclared ‘extern’
正常运行并在主行中打印clang
的{{1}} = 0(是,这是垃圾值),并且仍然大括号中的19个。
我猜a
在这里适用6.2.2。 7),而a
则没有。哪种解释是正确的,这里发生了什么?
我只能假设gcc
大括号中的clang
与主gcc
中的a
匹配,并且使其外部链接,然后看到它与文件范围a
冲突。而且,为什么不让括号static a
引用另一个文件中的a
(脚注31?)?
事实上,即使我确实知道C ++与C有所不同(并且我询问C),我目前的理解实际上也接近here中接受的答案。
解决方法
我唯一不了解的是为什么文件作用域a 在主体和花括号中可见吗?
在文件范围中声明的变量a
在main的块范围中可见
static int a = 19;
int main(void)
{
extern int a;
//...
直到main中的声明重新在文件作用域中声明变量。因此main中的变量表示在文件范围中声明的相同变量。
在复合语句的块范围内
int main(void)
{
extern int a;
{
extern int a;
//...
在main封闭范围内的变量a
的声明是可见的,直到在复合语句的块范围内的变量a
的声明为止。因此,在compound语句中声明的变量表示与在函数main的封闭块范围中声明的变量相同。这三个变量都表示具有内部链接的相同变量。
然后根据C标准(6.2.2标识符链接)进行第二个程序
7如果在翻译单元中,相同的标识符出现在两个 内部和外部的联系,行为是不确定的
程序具有未定义的行为,因为在函数main的块作用域中声明了变量
static int a = 19;
int main(void)
{
int a;
// ...
通过内部链接隐藏在文件范围中声明的变量。因此,根据C标准(6.2.2标识符的链接)
4对于使用存储类说明符extern声明的标识符 在该标识符的先前声明为 可见的31)如果先前声明指定内部还是外部 链接,在以后的声明中标识符的链接是 与先前声明中指定的链接相同。 如果以前没有 声明可见,或者如果先前声明未指定 链接,则标识符具有外部链接。
在复合语句的块作用域中声明的变量a
具有外部链接。结果,翻译单元中的同一标识符具有外部和内部链接。