Стандарт языка Си С99 TC (1113411), страница 31
Текст из файла (страница 31)
Moreover, if an identifier declared with internallinkage is used in an expression (other than as a part of the operand of a sizeofoperator whose result is an integer constant), there shall be exactly one external definitionfor the identifier in the translation unit.Semantics4As 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 they appear outside any function (and hence have file scope). As discussed in6.7, a declaration that also causes storage to be reserved for an object or a function namedby the identifier is a definition.5An 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 externallinkage is used in an expression (other than as part of the operand of a sizeof operatorwhose result is an integer constant), somewhere in the entire program there shall beexactly one external definition for the identifier; otherwise, there shall be no more thanone.140)140) Thus, if an identifier declared with external linkage is not used in an expression, there need be noexternal definition for it.140Language§6.9WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC36.9.1 Function definitionsSyntax1function-definition:declaration-specifiers declarator declaration-listopt compound-statementdeclaration-list:declarationdeclaration-list declarationConstraints2The identifier declared in a function definition (which is the name of the function) shallhave a function type, as specified by the declarator portion of the function definition.141)3The return type of a function shall be void or an object type other than array type.4The storage-class specifier, if any, in the declaration specifiers shall be either extern orstatic.5If the declarator includes a parameter type list, the declaration of each parameter shallinclude an identifier, except for the special case of a parameter list consisting of a singleparameter of type void, in which case there shall not be an identifier.
No declaration listshall follow.6If the declarator includes an identifier list, each declaration in the declaration list shallhave at least one declarator, those declarators shall declare only identifiers from theidentifier list, and every identifier in the identifier list shall be declared. An identifierdeclared as a typedef name shall not be redeclared as a parameter. The declarations in thedeclaration list shall contain no storage-class specifier other than register and noinitializations.141) The intent is that the type category in a function definition cannot be inherited from a typedef:typedef int F(void);F f, g;F f { /* ... */ }F g() { /* ... */ }int f(void) { /* ...
*/ }int g() { /* ... */ }F *e(void) { /* ... */ }F *((e))(void) { /* ... */ }int (*fp)(void);F *Fp;§6.9.1//////////////////////Languagetype F is ‘‘function with no parametersreturning int’’f and g both have type compatible with FWRONG: syntax/constraint errorWRONG: declares that g returns a functionRIGHT: f has type compatible with FRIGHT: g has type compatible with Fe returns a pointer to a functionsame: parentheses irrelevantfp points to a function that has type FFp points to a function that has type F141ISO/IEC 9899:TC3Committee Draft — Septermber 7, 2007WG14/N1256Semantics7The declarator in a function definition specifies the name of the function being definedand the identifiers of its parameters.
If the declarator includes a parameter type list, thelist also specifies the types of all the parameters; such a declarator also serves as afunction prototype for later calls to the same function in the same translation unit. If thedeclarator includes an identifier list,142) the types of the parameters shall be declared in afollowing declaration list. In either case, the type of each parameter is adjusted asdescribed in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.8If a function that accepts a variable number of arguments is defined without a parametertype list that ends with the ellipsis notation, the behavior is undefined.9Each parameter has automatic storage duration.
Its identifier is an lvalue, which is ineffect declared at the head of the compound statement that constitutes the function body(and therefore cannot be redeclared in the function body except in an enclosed block).The layout of the storage for parameters is unspecified.10On entry to the function, the size expressions of each variably modified parameter areevaluated and the value of each argument expression is converted to the type of thecorresponding parameter as if by assignment.
(Array expressions and functiondesignators as arguments were converted to pointers before the call.)11After all parameters have been assigned, the compound statement that constitutes thebody of the function definition is executed.12If the } that terminates a function is reached, and the value of the function call is used bythe caller, the behavior is undefined.13EXAMPLE 1In the following:extern int max(int a, int b){return a > b ? a : b;}extern is the storage-class specifier and int is the type specifier; max(int a, int b) is thefunction declarator; and{ return a > b ? a : b; }is the function body. The following similar definition uses the identifier-list form for the parameterdeclarations:142) See ‘‘future language directions’’ (6.11.7).142Language§6.9.1WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC3extern int max(a, b)int a, b;{return a > b ? a : b;}Here int a, b; is the declaration list for the parameters.
The difference between these two definitions isthat the first form acts as a prototype declaration that forces conversion of the arguments of subsequent callsto the function, whereas the second form does not.14EXAMPLE 2To pass one function to another, one might sayint f(void);/* ... */g(f);Then the definition of g might readvoid g(int (*funcp)(void)){/* ... */(*funcp)(); /* or funcp(); ...}*/or, equivalently,void g(int func(void)){/* ... */func(); /* or (*func)(); ...}*/6.9.2 External object definitionsSemantics1If the declaration of an identifier for an object has file scope and an initializer, thedeclaration is an external definition for the identifier.2A declaration of an identifier for an object that has file scope without an initializer, andwithout a storage-class specifier or with the storage-class specifier static, constitutes atentative definition.
If a translation unit contains one or more tentative definitions for anidentifier, and the translation unit contains no external definition for that identifier, thenthe behavior is exactly as if the translation unit contains a file scope declaration of thatidentifier, with the composite type as of the end of the translation unit, with an initializerequal to 0.3If the declaration of an identifier for an object is a tentative definition and has internallinkage, the declared type shall not be an incomplete type.§6.9.2Language143ISO/IEC 9899:TC34WG14/N1256EXAMPLE 1int i1 = 1;static int i2 = 2;extern int i3 = 3;int i4;static int i5;// definition, external linkage// definition, internal linkage// definition, external linkage// tentative definition, external linkage// tentative definition, internal linkageintintintintint// valid tentative definition, refers to previous// 6.2.2 renders undefined, linkage disagreement// valid tentative definition, refers to previous// valid tentative definition, refers to previous// 6.2.2 renders undefined, linkage disagreementi1;i2;i3;i4;i5;externexternexternexternextern5Committee Draft — Septermber 7, 2007EXAMPLE 2intintintintinti1;i2;i3;i4;i5;// refers to previous, whose linkage is external// refers to previous, whose linkage is internal// refers to previous, whose linkage is external// refers to previous, whose linkage is external// refers to previous, whose linkage is internalIf at the end of the translation unit containingint i[];the array i still has incomplete type, the implicit initializer causes it to have one element, which is set tozero on program startup.144Language§6.9.2WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC36.10 Preprocessing directivesSyntax1preprocessing-file:groupoptgroup:group-partgroup group-partgroup-part:if-sectioncontrol-linetext-line# non-directiveif-section:if-group elif-groupsopt else-groupopt endif-lineif-group:# ifconstant-expression new-line groupopt# ifdef identifier new-line groupopt# ifndef identifier new-line groupoptelif-groups:elif-groupelif-groups elif-group§6.10elif-group:# elifconstant-expression new-line groupoptelse-group:# elsenew-line groupoptendif-line:# endifnew-lineLanguage145ISO/IEC 9899:TC3Committee Draft — Septermber 7, 2007WG14/N1256control-line:# include pp-tokens new-line# define identifier replacement-list new-line# define identifier lparen identifier-listopt )replacement-list new-line# define identifier lparen ...