简体   繁体   English

为什么stdlib.h充满了外部函数原型和关于此的gcc差异

[英]Why is stdlib.h full of extern function prototypes and gcc discrepancy about this

I am aware about C linking rules presented in the following excerpts from C standard: 我知道以下C标准摘录中介绍的C链接规则:

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. 1 /可以通过称为链接的过程使在不同作用域或同一作用域中声明的标识符多次引用相同的对象或功能。 There are three kinds of linkage: external, internal, and none. 共有三种链接:外部链接,内部链接和无链接。

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. 2 /在构成整个程序的一组翻译单元和库中,带有外部链接的特定标识符的每个声明表示相同的对象或功能。 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/ 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. 3 /如果对象或函数的文件作用域标识符的声明包含静态的存储类说明符,则该标识符具有内部链接。

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. 4 /对于在可见该标识符的先前声明的范围内用存储类说明符extern声明的标识符,如果该先前声明指定了内部或外部链接,则该标识符在后面的声明中的链接与先前声明中指定的链接。 If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage. 如果没有在先声明可见,或者在先声明没有指定链接,则标识符具有外部链接。

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. 5 /如果函数标识符的声明中没有存储类说明符,则将其链接确定为与使用存储类说明符extern声明的完全相同。 If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external. 如果对象标识符的声明具有文件范围并且没有存储类说明符,则其链接是外部的。

6/ The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; 6 /以下标识符没有关联:声明为对象或函数以外的任何标识符; an identifier declared to be a function parameter; 声明为功能参数的标识符; a block scope identifier for an object declared without the storage-class specifier extern. 声明的没有存储类说明符extern的对象的块作用域标识符。

7/ If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined. 7 /如果在翻译单元内使用内部和外部链接显示相同的标识符,则行为未定义。

I understand that extern keyword is optional before functions declarations because they are external by default but there are some functions prototypes preceded by extern in stdlib.h such as: 我知道extern关键字在函数声明之前是可选的,因为默认情况下它们是外部的,但是在stdlib.h中有一些函数原型在extern之前,例如:

extern void qsort (void *__base, size_t __nmemb, size_t __size,
           __compar_fn_t __compar) __nonnull ((1, 4));

Also, why gcc handles situations described in point 7 differently when it comes to functions and variables. 同样,为什么在函数和变量方面,gcc为什么要处理第7点中描述的情况有所不同。 In this example both function foo and variable d are defined both in internal and external scope but only variable definition raises error: 在此示例中,函数foo和变量d均在内部和外部范围中定义,但是仅变量定义会引发错误:

static int foo(void); 
int foo(void); /* legal */

static double d;
double d; /* illegal */

One can freely place or not place extern before function declaration, so it should not be surprising that one can found it somewhere. 一个人可以在函数声明之前自由放置外部变量,也可以不放置外部变量,因此可以在某个地方找到它就不足为奇了。 Regarding second question: 关于第二个问题:

C11 draft (n1570.pdf) has example in page 159 related to tentative definitions: C11草案(n1570.pdf)在第159页中有与暂定定义相关的示例:

static int i5; // tentative definition, internal linkage
// ...
int i5; // 6.2.2 renders undefined, linkage disagreement
extern int i5; // refers to previous, internal linkage

6.2.2 is what you have posted. 6.2.2是您发布的内容。 So, it does not work in this case because there are two tentative definitions with different linkages, so there is p.7 violation. 因此,在这种情况下它不起作用,因为存在两个具有不同链接的暂定定义,因此存在p.7冲突。 On the other hand, it works with external specifier (as foo functions from your example), because p.4 is enforce - later declaration refers to linkage defined in first declaration. 另一方面,它与外部说明符一起工作(如示例中的foo函数),因为p.4是强制执行的-以后的声明引用第一个声明中定义的链接。 In other words, case with variables does not work because they are objects and tentative definition rules are involved. 换句话说,带有变量的大小写不起作用,因为它们是对象并且涉及临时定义规则。 At least standard contains explicit example which clearly explains what comittee wanted to say. 至少标准包含明确的示例,清楚地说明了委员会要说的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM