6.5 Expressions
- 6.5.1 Primary expressions
- 6.5.2 Postfix operators
- 6.5.3 Unary operators
- 6.5.4 Cast operators
- 6.5.5 Multiplicative operators
- 6.5.6 Additive operators
- 6.5.7 Bitwise shift operators
- 6.5.8 Relational operators
- 6.5.9 Equality operators
- 6.5.10 Bitwise AND operator
- 6.5.11 Bitwise exclusive OR operator
- 6.5.12 Bitwise inclusive OR operator
- 6.5.13 Logical AND operator
- 6.5.14 Logical OR operator
- 6.5.15 Conditional operator
- 6.5.16 Assignment operators
- 6.5.17 Comma operator
An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof.
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.[1] Furthermore, the prior value shall be read only to determine the value to be stored.[2]
The grouping of operators and operands is indicated by the syntax.[3] Except as specified later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.
Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |, collectively described as bitwise operators) are required to have operands that have integer type. These operators yield values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.
If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.
The effective type of an object for an access to its stored value is the declared type of the object, if any.[4] If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:[5]
a type compatible with the effective type of the object,
a qualified version of a type compatible with the effective type of the object,
a type that is the signed or unsigned type corresponding to the effective type of the object,
a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
a character type.
A floating expression may be contracted, that is, evaluated as though it were an atomic operation, thereby omitting rounding errors implied by the source code and the expression evaluation method.[6] The FP_CONTRACT pragma in <math.h> provides a way to disallow contracted expressions. Otherwise, whether and how expressions are contracted is implementation-defined.[7]
Forward References
Footnotes