为什么一个变量不能在 C 的 2 个文件中定义两次 [英] Why a variable can't be defined twice in 2 files in C

查看:25
本文介绍了为什么一个变量不能在 C 的 2 个文件中定义两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么我不能在 2 个 C 文件中有 int a;.我打算将两者结合起来以使其可执行.我从经验中知道我不能,但我想找到标准的 C99 在哪里说这个并密封我的理解.

Why can't I have int a; in 2 C files. I intend to combine both to make executable. I know from experience that I can't, but I want to find where the standard C99 says this and seal my understanding.

我正在从 http://www.open-std.org/jtc1/sc22/wg...docs/n1256.pdf.它在第 42 页上说:

I am reading ISO C99 standard from http://www.open-std.org/jtc1/sc22/wg...docs/n1256.pdf. It says on page 42:

6.2.2 标识符的链接

6.2.2 Linkages of identifiers

1 一个标识符声明在不同的范围或在同一范围内超过一次可以指代同一个对象或函数被调用的进程联动.共有三种链接:外部、内部和无.

1 An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage.There are three kinds of linkage: external, internal, and none.

2 在翻译单元集合中构成一个完整的图书馆程序,每个声明一个特定标识符与外部链接表示相同的对象或功能.在一个翻译单元内,每个标识符的声明与内部链接表示相同对象或函数.每个声明没有链接的标识符表示一个独特的实体.

2 In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.

3 如果声明一个文件作用域对象或函数的标识符包含存储类说明符静态,标识符有内部联动.

3 If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static,the identifier has internal linkage.

4 对于用存储类指定 extern 中的事先声明的范围该标识符是可见的,如果先验声明指定内部或外部联动,联动后面声明的标识符是与指定的链接相同先前的声明.如果没有先验声明是可见的,或者如果事先声明没有指明链接,那么标识符有外部联动.

4 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.

5 如果标识符的声明对于没有存储类的函数说明,它的联系是确定的就好像它是用声明的一样存储类指定 extern.If一个标识符的声明对象具有文件作用域并且没有存储类指定,其链接是外部.

5 If the declaration of an identifier for a function has no storage-class specifier,its linkage is determined exactly as if it were declared with the storage-class specifier extern.If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

阅读本文后,看起来如果我在 2 个源文件中声明一个变量,例如 say int a; .然后根据规则 5 和 4 两者都有外部链接.然后根据规则 2,两者都应该引用同一个对象.那么为什么编译器会产生问题.标准中的哪里暗示我们不能在 2 个源文件中这样声明,这应该会引发编译错误.首先,在标准中,它说 int a 是一个定义,然后它说 2 个定义实例是不可接受的.根据我的经验,我知道这是不允许的,但是如果我能在标准中找到它并印证我的理解,这对我将非常有用.

After reading this it looks that if I declare a variable like say int a; in 2 source files. then both have external linkage as per rule 5 and 4. and then as per rule 2, both should refer to the same object. Then why does the compiler create problem. Where in the standard it is hinted that we can't declare like this in 2 source files and this should throw compilation error. Firstly, where in the standard, it says that int a is a definition, and then where it says that 2 instances of definitions are not acceptable. I know that it is not allowed from my experience, but it would be very useful to me, if I can find this in the standard and seal my understanding.

以下从标准中摘录的内容是否符合此规则?还是我错过了那个胶水?:

声明指定集合的解释和属性标识符.一个定义标识符是一个声明标识符:——对于一个对象,导致为此保留的存储空间目的;——对于一个函数,包括函数体;——用于枚举常量或 typedef 名称,是(仅)标识符的声明.

A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that: —for an object, causes storage to be reserved for that object; —for a function, includes the function body; —for an enumeration constant or typedef name, is the (only) declaration of the identifier.

如 5.1.1.1 所述,单位预处理后的程序文本是翻译单元,由一个外部声明的顺序.这些被描述为外部"因为它们出现在任何函数之外(因此具有文件范围).作为在 6.7 中讨论过,声明也导致存储被保留用于一个对象或函数命名的标识符是一个定义.

As discussed in 5.1.1.1, the unit of program text after preprocessing is a translation unit, which consists of a sequence of external declarations. These are described as ‘‘external’’ because theyappear outside anyfunction (and hence have file scope). As discussed in 6.7, a declaration that also causes storage to be reserved for an object or a function named by the identifier is a definition.

外部定义是一个外部声明,同时也是一个定义函数的(内联除外)定义)或一个对象.如果用外部声明的标识符在表达式中使用链接(除了作为操作数的一部分一个 sizeof 运算符,其结果是整数常量),在某处整个程序应该有一个外部定义标识符;否则,将有不超过一个.

谢谢.

推荐答案

我认为你需要 6.9.2/2:

I think you need 6.9.2/2:

具有文件作用域的对象的标识符声明,没有初始值设定项,没有存储类说明符或带有存储类说明符static,构成一个暂定定义.如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则行为就像翻译单元包含该标识符的文件范围声明一样,复合类型为翻译单元的末尾,初始化器等于 0.

A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

和 6.9/5:

一个外部定义是一个外部声明,也是一个函数的定义(内联定义除外)或对象.如果使用外部声明的标识符链接在表达式中使用(除了作为 sizeof 运算符的操作数的一部分)其结果是一个整数常量),在整个程序的某个地方应该有标识符的一个外部定义;否则,将不超过一个.

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

基本上,int a; 是一个暂定定义.您可以在一个翻译单元中有多个暂定定义,但效果与具有一个非暂定外部定义相同(例如,int a = 0; 之类的东西).在程序中对具有外部链接的对象进行不止一个定义是违反 6.9/5 的.

Basically, int a; is a tentative definition. You can have multiple tentative definitions in a single translation unit but the effect is the same as having one non-tentative external definition (e.g. something like int a = 0;). Having more that one definition of an object with external linkage in a program is a violation of 6.9/5.

请注意,允许一个对象的多个外部定义是一种通用扩展",只要最多只有一个被初始化并且定义一致(见 J.5.11).

Note that it is a "common extension" to allow more than one external definitions of an object so long as at most only one is initialized and the definitions agree (see J.5.11).

这篇关于为什么一个变量不能在 C 的 2 个文件中定义两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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