Стандарт языка Си С99 TC (1113411), страница 27
Текст из файла (страница 27)
Array objects declared with the static or extern storage-class specifiercannot have a variable length array (VLA) type. However, an object declared with the static storageclass specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with aVM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions.extern int n;int A[n];extern int (*p2)[n];int B[100];// invalid: file scope VLA// invalid: file scope VM// valid: file scope but not VMvoid fvla(int m, int C[m][m]);// valid: VLA with prototype scopevoid fvla(int m, int C[m][m]){typedef int VLA[m][m];// valid: adjusted to auto pointer to VLAstruct tag {int (*y)[n];int z[n];};int D[m];static int E[m];extern int F[m];int (*s)[m];extern int (*r)[m];static int (*q)[m] = &B;// valid: block scope typedef VLA// invalid: y not ordinary identifier// invalid: z not ordinary identifier////////////valid: auto VLAinvalid: static block scope VLAinvalid: F has linkage and is VLAvalid: auto pointer to VLAinvalid: r has linkage and points to VLAvalid: q is a static block pointer to VLA}Forward references:initialization (6.7.8).function declarators (6.7.5.3), function definitions (6.9.1),6.7.5.3 Function declarators (including prototypes)Constraints1A function declarator shall not specify a return type that is a function type or an arraytype.2The only storage-class specifier that shall occur in a parameter declaration is register.3An identifier list in a function declarator that is not part of a definition of that functionshall be empty.4After adjustment, the parameters in a parameter type list in a function declarator that ispart of a definition of that function shall not have incomplete type.Semantics5If, in the declaration ‘‘T D1’’, D1 has the formD( parameter-type-list )orD( identifier-listopt )118Language§6.7.5.3WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC3and the type specified for ident in the declaration ‘‘T D’’ is ‘‘derived-declarator-type-listT ’’, then the type specified for ident is ‘‘derived-declarator-type-list function returningT ’’.6A parameter type list specifies the types of, and may declare identifiers for, theparameters of the function.7A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer totype’’, where the type qualifiers (if any) are those specified within the [ and ] of thearray type derivation.
If the keyword static also appears within the [ and ] of thearray type derivation, then for each call to the function, the value of the correspondingactual argument shall provide access to the first element of an array with at least as manyelements as specified by the size expression.8A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer tofunction returning type’’, as in 6.3.2.1.9If the list terminates with an ellipsis (, ...), no information about the number or typesof the parameters after the comma is supplied.125)10The special case of an unnamed parameter of type void as the only item in the listspecifies that the function has no parameters.11If, in a parameter declaration, an identifier can be treated either as a typedef name or as aparameter name, it shall be taken as a typedef name.12If the function declarator is not part of a definition of that function, parameters may haveincomplete type and may use the [*] notation in their sequences of declarator specifiersto specify variable length array types.13The storage-class specifier in the declaration specifiers for a parameter declaration, ifpresent, is ignored unless the declared parameter is one of the members of the parametertype list for a function definition.14An identifier list declares only the identifiers of the parameters of the function.
An emptylist in a function declarator that is part of a definition of that function specifies that thefunction has no parameters. The empty list in a function declarator that is not part of adefinition of that function specifies that no information about the number or types of theparameters is supplied.126)15For two function types to be compatible, both shall specify compatible return types.127)125) The macros defined in the <stdarg.h> header (7.15) may be used to access arguments thatcorrespond to the ellipsis.126) See ‘‘future language directions’’ (6.11.6).127) If both function types are ‘‘old style’’, parameter types are not compared.§6.7.5.3Language119ISO/IEC 9899:TC3Committee Draft — Septermber 7, 2007WG14/N1256Moreover, the parameter type lists, if both are present, shall agree in the number ofparameters and in use of the ellipsis terminator; corresponding parameters shall havecompatible types.
If one type has a parameter type list and the other type is specified by afunction declarator that is not part of a function definition and that contains an emptyidentifier list, the parameter list shall not have an ellipsis terminator and the type of eachparameter shall be compatible with the type that results from the application of thedefault argument promotions.
If one type has a parameter type list and the other type isspecified by a function definition that contains a (possibly empty) identifier list, both shallagree in the number of parameters, and the type of each prototype parameter shall becompatible with the type that results from the application of the default argumentpromotions to the type of the corresponding identifier. (In the determination of typecompatibility and of a composite type, each parameter declared with function or arraytype is taken as having the adjusted type and each parameter declared with qualified typeis taken as having the unqualified version of its declared type.)16EXAMPLE 1The declarationint f(void), *fip(), (*pfi)();declares a function f with no parameters returning an int, a function fip with no parameter specificationreturning a pointer to an int, and a pointer pfi to a function with no parameter specification returning anint.
It is especially useful to compare the last two. The binding of *fip() is *(fip()), so that thedeclaration suggests, and the same construction in an expression requires, the calling of a function fip,and then using indirection through the pointer result to yield an int. In the declarator (*pfi)(), theextra parentheses are necessary to indicate that indirection through a pointer to a function yields a functiondesignator, which is then used to call the function; it returns an int.17If the declaration occurs outside of any function, the identifiers have file scope and external linkage.
If thedeclaration occurs inside a function, the identifiers of the functions f and fip have block scope and eitherinternal or external linkage (depending on what file scope declarations for these identifiers are visible), andthe identifier of the pointer pfi has block scope and no linkage.18EXAMPLE 2The declarationint (*apfi[3])(int *x, int *y);declares an array apfi of three pointers to functions returning int. Each of these functions has twoparameters that are pointers to int. The identifiers x and y are declared for descriptive purposes only andgo out of scope at the end of the declaration of apfi.19EXAMPLE 3The declarationint (*fpfi(int (*)(long), int))(int, ...);declares a function fpfi that returns a pointer to a function returning an int.
The function fpfi has twoparameters: a pointer to a function returning an int (with one parameter of type long int), and an int.The pointer returned by fpfi points to a function that has one int parameter and accepts zero or moreadditional arguments of any type.120Language§6.7.5.3WG14/N125620EXAMPLE 4Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC3The following prototype has a variably modified parameter.void addscalar(int n, int m,double a[n][n*m+300], double x);int main(){double b[4][308];addscalar(4, 2, b, 2.17);return 0;}void addscalar(int n, int m,double a[n][n*m+300], double x){for (int i = 0; i < n; i++)for (int j = 0, k = n*m+300; j < k; j++)// a is a pointer to a VLA with n*m+300 elementsa[i][j] += x;}21EXAMPLE 5The following are all compatible function prototype declarators.doubledoubledoubledoublemaximum(intmaximum(intmaximum(intmaximum(intn,n,n,n,intintintintm,m,m,m,doubledoubledoubledoublea[n][m]);a[*][*]);a[ ][*]);a[ ][m]);as are:voidvoidvoidvoidf(doublef(doublef(doublef(double(* restrict a)[5]);a[restrict][5]);a[restrict 3][5]);a[restrict static 3][5]);(Note that the last declaration also specifies that the argument corresponding to a in any call to f must be anon-null pointer to the first of at least three arrays of 5 doubles, which the others do not.)Forward references: function definitions (6.9.1), type names (6.7.6).§6.7.5.3Language121ISO/IEC 9899:TC3Committee Draft — Septermber 7, 2007WG14/N12566.7.6 Type namesSyntax1type-name:specifier-qualifier-list abstract-declaratoroptabstract-declarator:pointerpointeropt direct-abstract-declaratordirect-abstract-declarator:( abstract-declarator )direct-abstract-declaratoropt [ type-qualifier-listoptassignment-expressionopt ]direct-abstract-declaratoropt [ static type-qualifier-listoptassignment-expression ]direct-abstract-declaratoropt [ type-qualifier-list staticassignment-expression ]direct-abstract-declaratoropt [ * ]direct-abstract-declaratoropt ( parameter-type-listopt )Semantics2In several contexts, it is necessary to specify a type.
This is accomplished using a typename, which is syntactically a declaration for a function or an object of that type thatomits the identifier.128)3EXAMPLE(a)(b)(c)(d)(e)(f)(g)(h)The constructionsintintintintintintintint**[3](*)[3](*)[*]*()(*)(void)(*const [])(unsigned int, ...)name respectively the types (a) int, (b) pointer to int, (c) array of three pointers to int, (d) pointer to anarray of three ints, (e) pointer to a variable length array of an unspecified number of ints, (f) functionwith no parameter specification returning a pointer to int, (g) pointer to function with no parametersreturning an int, and (h) array of an unspecified number of constant pointers to functions, each with oneparameter that has type unsigned int and an unspecified number of other parameters, returning anint.128) As indicated by the syntax, empty parentheses in a type name are interpreted as ‘‘function with noparameter specification’’, rather than redundant parentheses around the omitted identifier.122Language§6.7.6WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC36.7.7 Type definitionsSyntax1typedef-name:identifierConstraints2If a typedef name specifies a variably modified type then it shall have block scope.Semantics3In a declaration whose storage-class specifier is typedef, each declarator defines anidentifier to be a typedef name that denotes the type specified for the identifier in the waydescribed in 6.7.5.
Any array size expressions associated with variable length arraydeclarators are evaluated each time the declaration of the typedef name is reached in theorder of execution. A typedef declaration does not introduce a new type, only asynonym for the type so specified. That is, in the following declarations:typedef T type_ident;type_ident D;type_ident is defined as a typedef name with the type specified by the declarationspecifiers in T (known as T ), and the identifier in D has the type ‘‘derived-declaratortype-list T ’’ where the derived-declarator-type-list is specified by the declarators of D. Atypedef name shares the same name space as other identifiers declared in ordinarydeclarators.4EXAMPLE 1Aftertypedef int MILES, KLICKSP();typedef struct { double hi, lo; } range;the constructionsMILES distance;extern KLICKSP *metricp;range x;range z, *zp;are all valid declarations.