📄 express.gml
字号:
.ix 'expression'
.ix 'operator'
.ix 'operand'
.pp
An
.us expression
is a sequence of operators and operands that
describes how to,
.begbull $compact
.bull
calculate a value (eg. addition)
.bull
create side-effects (eg. assignment, increment)
.endbull
.pc
or both.
.pp
The order of execution of the expression is usually determined by
a mixture of,
.autonote
.note
.ix 'parentheses'
parentheses
.mono ()
..ct , which indicate to the compiler the desired grouping
of operations,
.note
.ix 'precedence'
.ix 'priority of operators'
.ix 'operator' 'priority'
.ix 'operator' 'precedence'
the precedence of operators, which describes the relative priority
of operators in the absence of parentheses,
.note
the common algebraic ordering,
.note
the associativity of operators.
.ix operator associativity
.ix 'associativity of operators'
.endnote
.pp
In most other cases, the order of execution is determined by the
compiler and may not be relied upon. Exceptions to this rule are
described in the relevant section.
Most users will find that the order of execution is well-defined
and intuitive.
However, when in doubt, use parentheses.
.pp
The table below summarizes the levels of precedence in expressions.
.im orderop
.im orddesc
.pp
An
.us exception
occurs when the operands for an operator are invalid. For example,
division by zero may cause an exception.
If an exception occurs, the behavior is undefined.
If an exception is a possibility, the program should be prepared
to handle it.
.pp
In the following sections, a formal syntax is used to describe
each level in the precedence table. This syntax is used in order
to completely describe the relationships between the various levels.
.*
.section Lvalues
.*
.pp
In order to understand certain components of expressions,
it is important to understand
the term
.ix lvalue
.us lvalue
..ct ..li .
.pp
An
.us lvalue
is an expression that designates an object.
The simplest form of
.us lvalue
is an identifier which is an object
(for example, an integer).
.pp
The type of the expression
may not be
.kw void
or a function. The term
.us lvalue
is derived from
.us l
..ct eft
.us value,
which refers to the fact that an
.us lvalue
is typically on the left side of an assignment expression.
.pp
If
.mono ptr
is a pointer to a type other than
.kw void
or a function, then both
.mono ptr
and
.mono *ptr
are
.us lvalues.
.pp
A
.ix lvalue modifiable
.ix 'modifiable lvalue'
.us modifiable lvalue
is an
.us lvalue
whose type is not an array or an incomplete type,
whose declaration does not contain the keyword
.kw const
..ct ,
and, if it is a structure or union, then none of its members contains
the keyword
.kw const
..ct ..li .
.*
.* .keep begin
.section Primary Expressions
.*
.ix 'primary expression'
.ix 'expression' 'primary'
.ix 'production'
.uillust begin
primary-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.identifier
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.constant
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.string-literal
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.:HP0.(:eHP0. expression :HP0.):eHP0.
.uillust end
.* .keep end
.pp
A
.us primary expression
is the simplest part of an expression. It consists of one of
the following:
:ZDL break termhi=0.
:ZDT.identifier
:ZDD.
An identifier that designates a function is called a
.ix 'function' 'designator'
.us function designator.
An identifier that designates an object
is an
.ix lvalue
.us lvalue.
:ZDT.constant
:ZDD.
A constant is a primary expression whose type depends on its form.
See "Constants".
:ZDT.string-literal
:ZDD.
.ix 'string literal'
.ix 'string'
A string literal is a primary expression whose
type is
"array of
.kw char
..ct ".
A string literal is also an
.us lvalue
(but is not modifiable).
:ZDT.expression inside parentheses
:ZDD.
The type and value of a parenthesized expression are the same as
for the expression without parentheses. It may be an
.us lvalue,
function designator or void expression.
:ZeDL.
.keep begin
.pp
Given these declarations,
.millust begin
int count;
int * ctrptr;
int f( int );
int g( int );
.millust end
.keep end
.pc
the following are all valid primary expressions:
.millust begin
count
3
3.2
'a'
"Hello there"
(count + 3)
(*(ctrptr+1))
(f( ++i ) * g( j++ ))
.millust end
.*
.keep begin
.*
.section Postfix Operators
.*
.ix 'operator' 'postfix'
.ix 'postfix operator'
.uillust begin
postfix-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.primary-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.array-subscripting-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.function-call-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.member-designator-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.post-increment-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.post-decrement-expression
.uillust end
.keep end
.beglevel
.*
.* .keep begin
.section Array Subscripting
.*
.ix 'array' 'subscripting'
.ix 'subscript'
.cillust begin
array-subscripting-expression:
.cbr
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression:MONO.[:eMONO.expression:MONO.]:eMONO.
.cillust end
.* .keep end
.pp
The general form for array subscripting is,
.millust array[index]
where
.mono array
must have the type "array of
.us type
..ct " or
"pointer to
.us type
..ct ", and
.mono index
must have an integral type. The result has
type "
..ct .us type
..ct ".
.pp
.mono array[index]
is equivalent to
.mono (*(array+index))
..ct ,
or the
..se hyphenmode=&syshy
..hy off
.mono index
..ct -th
..hy &hyphenmode
element of the array
.mono array
..ct ,
where the first
element is numbered zero. Note that
.mono index
is scaled automatically
to account for the size of the elements of
.mono array.
.pp
An alternate form for array subscripting is,
.millust index[array]
although this form is not commonly used.
.*
.keep begin
.section Function Calls
.*
.ix 'function' 'call'
.ix 'calling a function'
.cillust begin
function-call-expression:
.cbr
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression:MONO.():eMONO.
.cor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression
:MONO.(:eMONO.argument-expression-list:MONO.):eMONO.
.csk
argument-expression-list:
.cbr
&SYSRB.&SYSRB.&SYSRB.&SYSRB.:HP0.one or more:eHP0.
assignment-expression:HP0.s separated by commas:eHP0.
.cillust end
.keep end
.pp
A
.us postfix-expression
followed by parentheses containing zero or more comma-separated
expressions is a
.us function-call-expression
..ct ..li .
The postfix-expression denotes the function to be called, and must
evaluate to a pointer to a function.
.* returning
.* .kw void
.* or returning an object other than an array.
The simplest form of this expression is an identifier which is the name
of a function. For example,
.mono Fn()
calls the function
.mono Fn.
.pp
The expressions within the parentheses
denote the arguments to the function.
If a function
prototype has been declared, then the number of arguments must match
the parameter list in the prototype, and the arguments are converted
to the types specified in the prototype.
.pp
If the postfix-expression is simply an identifier, and no function
prototype declaration for that identifier
is in scope, then an implicit,
.cillust begin
.mono extern int
identifier:MONO.():eMONO.:MSEMI.
.cillust end
.pc
declaration is placed in the innermost block containing the
function call. This declares the function as having external
linkage,
.ix 'external linkage'
.ix 'linkage' 'external'
no information about its parameters is available, and the function
returns an integer.
.pp
The expressions are evaluated (in an undefined order) and the values
assigned to the parameters for the function. All arguments are passed
by value, allowing the function to modify its parameters without
affecting
the arguments used to create the parameters. However, an argument
can be a pointer to an object, in which case the function may
modify the object to which the pointer points.
.pp
If a function prototype is in scope at both a call to a function
and its definition (and if the prototypes are the same), then the
compiler will ensure that the required number and type of parameters
are present.
.pp
If no function prototype is in scope at a call to a function,
then the
.us default argument promotions
are performed.
(Integral types such as
.kw char
and
.kw short int
are converted to
.kw int
..ct ,
while
.kw float
values are converted to
.kw double
..ct ..li .)
When the function definition is encountered, if the parameter
types do not match the default argument promotions, then
the behavior is undefined. (Usually, the parameters to the function
will receive incorrect values.)
.pp
If a function prototype has been declared at a call to a function,
then each argument is converted, as if by assignment, to the type
of the corresponding parameter. When the function definition is
encountered, if the types of the parameters do not match the types
of the parameters in the function prototype, the behavior is
undefined.
.pp
If the
.ix ellipsis
ellipsis (
..ct .mono ,...
..ct )
notation is used in a function prototype,
then those arguments in a function call that correspond to the
ellipsis have only the default argument promotions performed on
them.
(See the chapter "Functions" for a complete description of the
ellipsis notation.)
.pp
Function calls may be
..ix 'function' 'recursion'
..ix 'recursion'
recursive.
Functions
may call themselves either directly, or via other functions.
.pp
The following are some examples of function calls:
.millust begin
putchar( 'x' );
chr = getchar();
valid = isdigit( chr );
printf( "chr = %c, valid = %2x\n", chr, valid );
fnptr = &MyFunction;
(*fnptr)( parm1, parm2 );
fnptr( parm1, parm2 );
.millust end
.*
.* .keep begin
.section Structure and Union Members
.*
.ix 'structure' 'member'
.ix 'union' 'member'
.ix 'member' 'of structure'
.ix 'member' 'of union'
.uillust begin
member-designator-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression . identifier
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression:MONO.->:eMONO.identifier
.uillust end
.* .keep end
.pp
The first operand of the .
operator
.ix 'dot operator'
.ix 'operator' 'dot'
.ix 'operator' '.'
must be an object with a structure or union type. The second operand
must be the name of a member of that type.
The result is the value of the member, and is an lvalue if the
first operand is also an lvalue.
.pp
The first operand of the
.mono ->
operator
.ix 'arrow operator'
.ix 'operator' 'arrow'
.ix 'operator' '->'
must be a pointer to an
object with a structure or union type. The second operand
must be the name of a member of that type.
The result is the value of the member
of the structure or union to which
the first expression points, and is an lvalue.
.*
.keep begin
.section Post-Increment and Post-Decrement
.*
.ix 'post-increment'
.ix 'post-decrement'
.ix 'increment'
.ix 'decrement'
.ix 'operator' 'post-increment'
.ix 'operator' '++'
.ix 'operator' 'post-decrement'
.ix 'operator' '--'
.uillust begin
post-increment-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression:MONO.++:eMONO.
post-decrement-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression:MONO.--:eMONO.
.uillust end
.keep end
.pp
The operand of post-increment and post-decrement must be a modifiable
lvalue, and a scalar (not a structure, union or array).
.pp
The effect of the operation is that
the operand is incremented or decremented by 1, adjusted for the
type of the operand. For example, if the operand is declared to be
a "pointer to
.us type
..ct ", then the increment or decrement will be by the value
.monoon
sizeof(&SYSRB.:HP1.type:eHP1.&SYSRB.)
.monooff
..ct ..li .
.pp
The result of both post-increment and post-decrement (if it is just
a subexpression of a larger expression)
is the original,
unmodified value of the operand.
In other words, the original value of the operand is used in the
expression, and then it is incremented or decremented.
Whether the operand is incremented immediately after use or after
completion of execution of the expression is undefined. Consider the
statements,
.millust begin
int i = 2;
int j;
j = (i++) + (i++);
.millust end
.pc
Depending on the compiler,
.mono j
may get the value 4 or 5. If the increments are delayed until after
the expression is evaluated,
.mono j
gets the value
.monoon
2&SYSRB.+&SYSRB.2.
.monooff
If the increment of
.mono i
happens immediately after its value is retrieved, then
.mono j
gets the value
.monoon
2&SYSRB.+&SYSRB.3.
.monooff
.* .*
.* .*********************************************************************
.* .*
.* ..if '&target' eq 'PC' ..th ..do begin
.* .shade begin
.* The &wcboth. compilers do post-increment and decrement immediately,
.* so the result of the above expression will be 5.
.* No program should rely upon this order.
.* .shade end
.* ..do end
.* ..if '&target' eq 'PC 370' ..th ..do begin
.* .shade begin
.* The &wcall. compilers
.* do post-increment and decrement immediately,
.* so the result of the above expression will be 5.
.* No program should rely upon this order.
.* .shade end
.* ..do end
.* .*
.* .*********************************************************************
.*
.keep begin
.pp
To avoid ambiguity, the above expression could be written as:
.millust begin
j = i + i;
i += 2;
.millust end
.keep end
.endlevel
.*
.keep begin
.section Unary Operators
.*
.ix 'operator' 'unary'
.ix 'unary operator'
.uillust begin
unary-expression:
&SYSRB.&SYSRB.&SYSRB.&SYSRB.postfix-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.pre-increment-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.pre-decrement-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.unary-operator cast-expression
.uor
&SYSRB.&SYSRB.&SYSRB.&SYSRB.sizeof-expression
.uillust end
.keep end
.cillust begin
.us unary-operator:
one of
.cbr
.monoon
&SYSRB.&SYSRB.&SYSRB.&SYSRB.& * + - ~~ !
.monooff
.cillust end
.beglevel
.*
.* .keep begin
.section Pre-Increment and Pre-Decrement Operators
.*
.ix 'increment'
.ix 'pre-increment'
.ix 'decrement'
.ix 'pre-decrement'
.ix 'operator' 'pre-increment'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -