对于带有extern的新声明,如何解决多个先前的声明? [英] How are multiple prior declarations resolved for a new declaration with extern?

查看:287
本文介绍了对于带有extern的新声明,如何解决多个先前的声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第三个x在其中应指什么:

What should the third x refer to in:

#include <stdio.h>

static char x = '1';

int main(void)
{
    char x = '2';
    {
        extern char x;
        printf("%c\n", x);
    }
}

此问题出现在此答案中,并且:

This arose in this answer, and:

  • 在Apple LLVM 9.1.0 clang-902-0.39.2中,extern char xx引用第一个x,并打印"1".
  • GCC 8.2不接受该源文本.,抱怨道:错误:变量先前声明为'静态"重新声明为外部"".
  • In Apple LLVM 9.1.0 clang-902-0.39.2, the x of extern char x refers to the first x, and "1" is printed.
  • GCC 8.2 does not accept this source text., complaining: "error: variable previously declared 'static' redeclared 'extern'".

C 2018 6.2.2 4说:

C 2018 6.2.2 4 says:

对于在可见该标识符的先前声明的范围中用存储类说明符 extern 声明的标识符,如果该先前声明指定了内部或外部链接,则该标识符的链接在后面的声明中,与在前面的声明中指定的链接相同.如果没有任何在先声明可见,或者在先声明没有指定链接,则标识符具有外部链接.

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

由于有两个x的在先声明,因此以下每个"if"子句的条件为true,第一个用于第一个在先声明,第二个用于第二个在先声明:

Since there are two prior declarations of x, the condition of each of the following "if" clauses is true, the first for the first prior declaration, and the second for the second prior declaration:

  • …如果在先声明指定内部或外部链接,则在后一个声明中标识符的链接与在先声明中指定的链接相同.
  • …如果先前声明未指定任何链接,则标识符具有外部链接.

这里的Clang行为与使用第一个子句是一致的,因此第三个x具有内部链接,并且与第一个x引用相同的对象. GCC在这里的行为与使用第二个子句是一致的,因此第三个x具有外部链接,并且与第一个x具有内部链接冲突.

Clang’s behavior here is consistent with using the first clause, so that the third x has internal linkage and refers to the same object as the first x. GCC’s behavior here is consistent with using the second clause, so that the third x has external linkage and conflicts with the first x, which has internal linkage.

C标准是否为我们提供了一种方法来解决其中的一种情况?

Does the C standard give us a way to resolve which of these should be the case?

推荐答案

第三个声明extern char x应该基于C 2018 6.2.2 4声明具有外部链接的x,它说:

The third declaration, extern char x, should declare x with external linkage, based on C 2018 6.2.2 4, which says:

对于在可见该标识符的先前声明的范围中用存储类说明符 extern 声明的标识符,如果该先前声明指定了内部或外部链接,则该标识符的链接在后面的声明中,与在前面的声明中指定的链接相同.如果没有任何在先声明可见,或者在先声明未指定任何链接,则标识符具有外部链接.

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

在声明extern char x处,x的第一个声明不可见,因为它已被第二个声明隐藏.因此,它不符合该标识符的先前声明可见"的条件. x的第二个声明是可见的,因此对于上一段而言,它是先前的声明".

At the declaration extern char x, the first declaration of x is not visible, as it has been hidden by the second declaration. Therefore, it does not qualify for "a prior declaration of that identifier is visible." The second declaration of x is visible, so it is a "prior declaration" for the purposes of the above paragraph.

然后,最后一句话应该控制:先前的声明未指定任何链接(6.2.2 6,没有extern的块范围标识符没有链接),因此第三个x具有外部链接.

Then the last sentence should control: The prior declaration specifies no linkage (6.2.2 6, a block-scope identifier without extern has no linkage), so the third x has external linkage.

则违反了6.2.2 7,因为第一个x具有内部链接,而第三个x具有外部链接:

Then 6.2.2 7 is violated because the first x has internal linkage and the third x has external linkage:

如果在翻译单元中,具有内部和外部链接的相同标识符同时出现,则行为是不确定的.

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

由于没有违反语法规则或约束,因此标准不需要C实现来报告诊断.由于行为是不确定的,因此它可以执行任何操作,包括接受此代码并使第三个x引用与第一个x相同的对象.因此,在这方面,Clang和GCC的行为均未违反标准.但是,由于违反了6.2.2 7的要求,因此诊断可能是更可取的选择,而缺少该诊断程序可能会导致Clang的缺陷.

Since no syntax rule or constraint is violated, the C implementation is not required by the standard to report a diagnostic. Since the behavior is undefined, it may do anything, including accept this code and make the third x refer to the same object as the first x. Therefore, neither Clang nor GCC’s behaviors violate the standard in this regard. However, since 6.2.2 7 is violated, a diagnostic may be preferred, and its absence could be consider a defect of Clang.

(向 Paul Ogilvie

(Credit to Paul Ogilvie and T.C. for informing my thinking on this with their comments.)

这篇关于对于带有extern的新声明,如何解决多个先前的声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆