Стандарт языка Си С99 TC (1113411), страница 25
Текст из файла (страница 25)
This association, defined in 6.7.3.1 below, requires that all accesses tothat object use, directly or indirectly, the value of that particular pointer.117) The intendeduse of the restrict qualifier (like the register storage class) is to promoteoptimization, and deleting all instances of the qualifier from all preprocessing translationunits composing a conforming program does not change its meaning (i.e., observablebehavior).8If the specification of an array type includes any type qualifiers, the element type is soqualified, not the array type.
If the specification of a function type includes any typequalifiers, the behavior is undefined.118)9For two qualified types to be compatible, both shall have the identically qualified versionof a compatible type; the order of type qualifiers within a list of specifiers or qualifiersdoes not affect the specified type.10EXAMPLE 1An object declaredextern const volatile int real_time_clock;may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.115) This applies to those objects that behave as if they were defined with qualified types, even if they arenever actually defined as objects in the program (such as an object at a memory-mapped input/outputaddress).116) A volatile declaration may be used to describe an object corresponding to a memory-mappedinput/output port or an object accessed by an asynchronously interrupting function.
Actions onobjects so declared shall not be ‘‘optimized out’’ by an implementation or reordered except aspermitted by the rules for evaluating expressions.117) For example, a statement that assigns a value returned by malloc to a single pointer establishes thisassociation between the allocated object and the pointer.118) Both of these can occur through the use of typedefs.§6.7.3Language109ISO/IEC 9899:TC311Committee Draft — Septermber 7, 2007WG14/N1256EXAMPLE 2 The following declarations and expressions illustrate the behavior when type qualifiersmodify an aggregate type:const struct s { int mem; } cs = { 1 };struct s ncs; // the object ncs is modifiabletypedef int A[2][3];const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const intint *pi;const int *pci;ncs = cs;cs = ncs;pi = &ncs.mem;pi = &cs.mem;pci = &cs.mem;pi = a[0];////////////validviolates modifiable lvalue constraint for =validviolates type constraints for =validinvalid: a[0] has type ‘‘const int *’’6.7.3.1 Formal definition of restrict1Let D be a declaration of an ordinary identifier that provides a means of designating anobject P as a restrict-qualified pointer to type T.2If D appears inside a block and does not have storage class extern, let B denote theblock.
If D appears in the list of parameter declarations of a function definition, let Bdenote the associated block. Otherwise, let B denote the block of main (or the block ofwhatever function is called at program startup in a freestanding environment).3In what follows, a pointer expression E is said to be based on object P if (at somesequence point in the execution of B prior to the evaluation of E) modifying P to point toa copy of the array object into which it formerly pointed would change the value of E.119)Note that ‘‘based’’ is defined only for expressions with pointer types.4During each execution of B, let L be any lvalue that has &L based on P.
If L is used toaccess the value of the object X that it designates, and X is also modified (by any means),then the following requirements apply: T shall not be const-qualified. Every other lvalueused to access the value of X shall also have its address based on P. Every access thatmodifies X shall be considered also to modify P, for the purposes of this subclause. If Pis assigned the value of a pointer expression E that is based on another restricted pointerobject P2, associated with block B2, then either the execution of B2 shall begin beforethe execution of B, or the execution of B2 shall end prior to the assignment. If theserequirements are not met, then the behavior is undefined.5Here an execution of B means that portion of the execution of the program that wouldcorrespond to the lifetime of an object with scalar type and automatic storage duration119) In other words, E depends on the value of P itself rather than on the value of an object referencedindirectly through P.
For example, if identifier p has type (int **restrict), then the pointerexpressions p and p+1 are based on the restricted pointer object designated by p, but the pointerexpressions *p and p[1] are not.110Language§6.7.3.1WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC3associated with B.6A translator is free to ignore any or all aliasing implications of uses of restrict.7EXAMPLE 1The file scope declarationsint * restrict a;int * restrict b;extern int c[];assert that if an object is accessed using one of a, b, or c, and that object is modified anywhere in theprogram, then it is never accessed using either of the other two.8EXAMPLE 2 The function parameter declarations in the following examplevoid f(int n, int * restrict p, int * restrict q){while (n-- > 0)*p++ = *q++;}assert that, during each execution of the function, if an object is accessed through one of the pointerparameters, then it is not also accessed through the other.9The benefit of the restrict qualifiers is that they enable a translator to make an effective dependenceanalysis of function f without examining any of the calls of f in the program.
The cost is that theprogrammer has to examine all of those calls to ensure that none give undefined behavior. For example, thesecond call of f in g has undefined behavior because each of d[1] through d[49] is accessed throughboth p and q.void g(void){extern int d[100];f(50, d + 50, d); // validf(50, d + 1, d); // undefined behavior}10EXAMPLE 3The function parameter declarationsvoid h(int n, int * restrict p, int * restrict q, int * restrict r){int i;for (i = 0; i < n; i++)p[i] = q[i] + r[i];}illustrate how an unmodified object can be aliased through two restricted pointers.
In particular, if a and bare disjoint arrays, a call of the form h(100, a, b, b) has defined behavior, because array b is notmodified within function h.11EXAMPLE 4 The rule limiting assignments between restricted pointers does not distinguish between afunction call and an equivalent nested block. With one exception, only ‘‘outer-to-inner’’ assignmentsbetween restricted pointers declared in nested blocks have defined behavior.§6.7.3.1Language111ISO/IEC 9899:TC3Committee Draft — Septermber 7, 2007WG14/N1256{int * restrict p1;int * restrict q1;p1 = q1; // undefined behavior{int * restrict p2 = p1; // validint * restrict q2 = q1; // validp1 = q2;// undefined behaviorp2 = q2;// undefined behavior}}12The one exception allows the value of a restricted pointer to be carried out of the block in which it (or, moreprecisely, the ordinary identifier used to designate it) is declared when that block finishes execution.
Forexample, this permits new_vector to return a vector.typedef struct { int n; float * restrict v; } vector;vector new_vector(int n){vector t;t.n = n;t.v = malloc(n * sizeof (float));return t;}6.7.4 Function specifiersSyntax1function-specifier:inlineConstraints2Function specifiers shall be used only in the declaration of an identifier for a function.3An inline definition of a function with external linkage shall not contain a definition of amodifiable object with static storage duration, and shall not contain a reference to anidentifier with internal linkage.4In a hosted environment, the inline function specifier shall not appear in a declarationof main.Semantics5A function declared with an inline function specifier is an inline function.
Thefunction specifier may appear more than once; the behavior is the same as if it appearedonly once. Making a function an inline function suggests that calls to the function be asfast as possible.120) The extent to which such suggestions are effective isimplementation-defined.121)6Any function with internal linkage can be an inline function. For a function with externallinkage, the following restrictions apply: If a function is declared with an inline112Language§6.7.4WG14/N1256Committee Draft — Septermber 7, 2007ISO/IEC 9899:TC3function specifier, then it shall also be defined in the same translation unit. If all of thefile scope declarations for a function in a translation unit include the inline functionspecifier without extern, then the definition in that translation unit is an inlinedefinition.
An inline definition does not provide an external definition for the function,and does not forbid an external definition in another translation unit. An inline definitionprovides an alternative to an external definition, which a translator may use to implementany call to the function in the same translation unit. It is unspecified whether a call to thefunction uses the inline definition or the external definition.122)7EXAMPLE The declaration of an inline function with external linkage can result in either an externaldefinition, or a definition available for use only within the translation unit. A file scope declaration withextern creates an external definition.
The following example shows an entire translation unit.inline double fahr(double t){return (9.0 * t) / 5.0 + 32.0;}inline double cels(double t){return (5.0 * (t - 32.0)) / 9.0;}extern double fahr(double);// creates an external definitiondouble convert(int is_fahr, double temp){/* A translator may perform inline substitutions */return is_fahr ? cels(temp) : fahr(temp);}8Note that the definition of fahr is an external definition because fahr is also declared with extern, butthe definition of cels is an inline definition. Because cels has external linkage and is referenced, anexternal definition has to appear in another translation unit (see 6.9); the inline definition and the externaldefinition are distinct and either may be used for the call.Forward references: function definitions (6.9.1).120) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inlinesubstitution’’.