C语言中的undefined behavior系列(1) linkage of identifier

我叫嗷嗷,我喜欢乱叫,我是C/C++语言的偏执狂,嗷嗷~~~~

这里是我对于C语言中的那些undefined behavior的理解。

本系列其他文章的传送门: C语言中的undefined behavior/unspecified behavior - 序

嗷嗷的话: 本文里只要是大段大段的英文,都来至C99标准。所有的中文注释都是我对标准的理解。在文中使用的编译器是开了C99支持Intel C Compiler 11 for Windows.

++++++++++++我是华丽的分割线+++++++++++++++++++++++++++++++

— The same identifier has both internal and external linkage in the same translation unit (6.2.2).

如果某个identifier在一个c语言源文件中,同时有internal和external的linkage的话,这是一个undefinedbehavior.

首先来理一下相关的知识点:

  1. 一共有三种linkage: external, internal, and none. [a][b]
  2. 被static修饰的全局identifier是internal linkage.
  3. 一个identifier的声明(declaration)被external所修饰。那么分两种情况,第一,如果在这个声明之前没有对这个identifier任何可见的声明,则这个identifier是external linkage. 第二,如果在这个声明之前有对这个identifier的可见声明,则它linkage和前一个声明一样。[c]
  4. 没有加任何修饰的声明默认属于被external修饰。
  5. 只有函数和对象才存在linkage. 比如说声明函数参数的identifier没有linkage.
  6. 如果一个声明有被初始化,那么这个declaration就是definition. [d]
  7. 一个declaration如果没有初始化,也没有任何修饰符,我们就叫他tentative definition[e]

 好我们来看个例子来说明这个问题,他来至于C99的标准文档中。如果在一个文件中如下声明变量,那些是undefined behavior.

 

代码
int i1 = 1; // definition, external linkage
static int i2 = 2; // definition, internal linkage
extern int i3 = 3; // definition, external linkage
int i4; // tentative definition, external linkage
static int i5; // tentative definition, internal linkage

int i1; // valid tentative definition, refers to pre vious
int i2; // 6.2.2 renders undefined, linkage disagreement
int i3; // valid tentative definition, refers to previous
int i4; // valid tentative definition, refers to previous
int i5; // 6.2.2 renders undefined, linkage disagreement

extern int i1; // refers to previous, whose linkage is external
extern int i2; // refers to previous, whose linkage is internal
extern int i3; // refers to previous, whose linkage is external
extern int i4; // refers to previous, whose linkage is external
extern int i5; // refers to previous, whose linkage is internal
  • Reference

C99-6.2.2 Linkagesof identifiers:

[a] An identifier declared in differentscopes or in the same scope more than once can be made to refer to the same object or unction by a process calledlinkage.21) There are threekinds of linkage: external, internal, and none.

[b]  Inthe set of translation units and libraries that constitutes an entire program,each declaration of aparticular dentifier with external linkage denotes the same object or function. Within one translation unit, eachdeclaration of an identifier with internal linkage denotes the same object or function. Each declaration of anidentifier with no linkagedenotes a unique entity.

[c]For an identifier declared with thestorage-class specifier extern in a scope in which a prior declaration of that identifier is visible,23) if the priordeclaration specifies internal or external linkage, the linkage of the identifier at the laterdeclaration is the same as the linkagespecified at the prior declaration. If no prior declaration is visible, or ifthe prior

declarationspecifies no linkage, then the identifier has external linkage.

 C99-6.9.2 External object definitions

[d]If the declaration of an identifier foran object has file scope and an initializer, the declaration is an external definition for the identifier.

[e] A declaration of an identifier for anobject that has file scope without an initializer, and without a storage-class pecifier or with the storage-class specifierstatic, constitutes a tentativedefinition. If a translation unit contains one or more tentative definitionsfor an identifier, and thetranslation unit contains no external definition for that identifier, then the behavior is exactly as if thetranslation unit contains a file scope declaration of that identifier, with the composite type as ofthe end of the translation unit, with an initializer equal to 0.

原文地址:https://www.cnblogs.com/aoaoblogs/p/1810072.html