An expression is a sequence of operators and operands. It may compute a value, designate an object or function, or produce side effects (C17 6.5). The standard defines precedence through its grammar; the table below is derived from it.
Operator precedence
| Level | Operators | Description | Associativity | Clause |
|---|---|---|---|---|
| 1 | x++ x-- | Postfix increment and decrement | Left to right | 6.5.2.4 |
| 1 | f() | Function call | Left to right | 6.5.2.2 |
| 1 | a[i] | Array subscript | Left to right | 6.5.2.1 |
| 1 | . -> | Member access, member access through a pointer | Left to right | 6.5.2.3 |
| 1 | (type){…} | Compound literal (C99) | Left to right | 6.5.2.5 |
| 2 | ++x --x | Prefix increment and decrement | Right to left | 6.5.3.1 |
| 2 | + - | Unary plus and minus | Right to left | 6.5.3.3 |
| 2 | ! ~ | Logical NOT, bitwise NOT | Right to left | 6.5.3.3 |
| 2 | (type) | Cast | Right to left | 6.5.4 |
| 2 | * & | Indirection, address-of | Right to left | 6.5.3.2 |
| 2 | sizeof _Alignof | Size of, alignment of (C11) | Right to left | 6.5.3.4 |
| 3 | * / % | Multiplication, division, remainder | Left to right | 6.5.5 |
| 4 | + - | Addition, subtraction | Left to right | 6.5.6 |
| 5 | << >> | Bitwise shifts | Left to right | 6.5.7 |
| 6 | < <= > >= | Relational | Left to right | 6.5.8 |
| 7 | == != | Equality | Left to right | 6.5.9 |
| 8 | & | Bitwise AND | Left to right | 6.5.10 |
| 9 | ^ | Bitwise exclusive OR | Left to right | 6.5.11 |
| 10 | | | Bitwise inclusive OR | Left to right | 6.5.12 |
| 11 | && | Logical AND | Left to right | 6.5.13 |
| 12 | || | Logical OR | Left to right | 6.5.14 |
| 13 | ?: | Conditional | Right to left | 6.5.15 |
| 14 | = += -= *= /= %= <<= >>= &= ^= |= | Assignment | Right to left | 6.5.16 |
| 15 | , | Comma | Left to right | 6.5.17 |
A higher position in the table binds more tightly. A few consequences of the grammar do not fit a table:
- The middle operand of
?:is parsed as if parenthesised, whatever its operators. sizeof (int) * pis parsed as(sizeof(int)) * p: the operand ofsizeofcannot be a cast.- The left operand of an assignment must be a unary expression, so
a < b ? c : d = 1does not parse. Many compilers accept it then report a different error. *p++means*(p++), anda + b << 1means(a + b) << 1.- Precedence is low for bitwise operators, so
x & 1 == 0meansx & (1 == 0).
Precedence and associativity decide how an expression groups. They do not decide which operand is evaluated first, which is usually unspecified. See Sequence points.
Lvalues
An lvalue is an expression that may designate an object (C17 6.3.2.1). A
modifiable lvalue may be assigned to: it does not have array type, or an incomplete
type, or a const-qualified type, and it is not a structure or union with a
const member.
| Is an lvalue | Not an lvalue |
|---|---|
| The name of an object | A constant other than a string literal |
*p, a[i] | The result of a cast |
x.m if x is an lvalue, and p->m | The result of an assignment, or ++x, or x++ |
| A string literal | A function call, or a ? b : c, or a comma expression |
| A compound literal | An enumeration constant |
| A parenthesised lvalue |
In C, unlike C++, assignment does not produce an lvalue, and neither does a prefix increment.
An lvalue that is read loses its lvalue status and its qualifiers. The operand of
sizeof, of unary &, of ++ and --, and
the left operand of . or of an assignment stay lvalues. Reading an uninitialised
automatic object is undefined.
Arithmetic operators
- Operands undergo the usual arithmetic conversions.
- Signed integer overflow is undefined. Unsigned arithmetic wraps modulo 2N (C17 6.2.5).
- Integer division truncates toward zero since C99, and
(a / b) * b + a % bequalsa. In C89 the direction was implementation-defined for negative operands. - Dividing by zero, for integers or for the remainder operator, is undefined.
INT_MIN / -1is undefined, because the result does not fit.- The operands of
%must have integer type.
Increment and decrement
++x yields the new value of x. x++ yields the old
value. Both add 1 to the lvalue. A pointer moves by one element.
Bitwise and shift operators
~,&,^and|work on integer operands after the usual promotions.- The result of a shift has the type of the promoted left operand.
- A shift by a negative amount, or by at least the width of the promoted left operand, is undefined (C17 6.5.7).
a << non a negative signeda, or when the result does not fit, is undefined.a >> nof a negative signedais implementation-defined. Most compilers shift in copies of the sign bit.
Comparison and logical operators
Relational, equality and logical operators yield an int, 0 or 1. An expression
used as a condition tests against 0, so any scalar may be a condition. Comparisons chain as
arithmetic: 1 < x < 3 means (1 < x) < 3, which is always
true.
&& and || evaluate left to right, and stop as soon as the
result is known (C17 6.5.13, 6.5.14). Each has a
sequence point after its first operand.
Equality of floating values follows the rules of the floating format, so NaN compares unequal to itself. Comparing floating values for exact equality is often an error.
Conditional operator
conditional-expression:
logical-OR-expression ? expression : conditional-expression
The first operand must be scalar, and is tested against 0. A sequence point follows it. Only
the second or the third operand is then evaluated. If both have arithmetic type the
result has the type after the usual arithmetic conversions. They may also be two
compatible structures, two void expressions, or pointers, with rules for
null pointer constants and void * (C17 6.5.15). The result is not an lvalue.
Assignment
Simple assignment converts the right operand to the type of the left. The result is the new
value of the left operand and has its unqualified type (C17 6.5.16). a = b = 0
assigns right to left, and so works.
A compound assignment a += b is the same as a = a + b except that
a is evaluated once. The left operand of any assignment must be a modifiable
lvalue. The side effect of updating the left operand is sequenced after the value computations
of both operands.
Comma operator
In a, b, a is evaluated and its value discarded, then there is a
sequence point, then b is evaluated (C17 6.5.17). The result is the value and
type of b, and is not an lvalue. Commas in function arguments and initialisers
are separators, not this operator. Parentheses make it the operator:
f((a, b), c) calls f with two arguments.
sizeof and _Alignof
sizeof yields the size of a type or expression in bytes, as a constant of type
size_t (C17 6.5.3.4). The operand is not evaluated, unless it has
variable length array type. Brackets are
needed only around a type name: sizeof x and sizeof(int). It may not
be applied to a function, an incomplete type or a bit-field.
_Alignof (C11), spelled alignof in C23, gives the alignment of a
type (see Alignment).
Casts
cast-expression:
unary-expression
( type-name ) cast-expression
A cast converts the value of its operand to the named type, and the result is not an
lvalue (C17 6.5.4). The type must be scalar or void, and the operand must be
scalar, except that any value can be cast to void. See
Conversions for what happens to the value.
A cast can silence a warning but it cannot make an invalid operation valid.
Generic selection
generic-selection:
_Generic ( assignment-expression , generic-assoc-list )
generic-association:
type-name : assignment-expression
default : assignment-expression
_Generic (C11) chooses one of its expressions by the type of its first
operand, at compile time (C17 6.5.1.1). The first operand is not evaluated. Its type is taken
after lvalue conversion, so qualifiers and array types are adjusted. Exactly one association
must match, or default is used.
#define type_name(x) _Generic((x), \
int: "int", \
double: "double", \
char *: "char *", \
default: "other")
type_name(1.0); /* "double" */
_Generic is the basis of type-generic macros such as those in <tgmath.h>Constant expressions
A constant expression can be evaluated during translation (C17 6.6). It may not contain assignment, increment, decrement, function calls or the comma operator, except in a part that is not evaluated.
| Kind | May be used for |
|---|---|
| Integer constant expression | Fixed array sizes, case labels, bit-field widths, enumerator values, _Alignas and static assertions |
| Arithmetic constant expression | Initialisers of arithmetic objects with static storage |
| Address constant | Initialisers of pointer objects with static storage: a null pointer, or the address of a static object or function, plus or minus an integer |
A named const object is not a constant expression. An
constexpr object, in
C23, is.
Sequence points and evaluation order
A sequence point is a point at which all side effects of previous evaluations are complete (C17 5.1.2.3, Annex C). C11 restated this in terms of a sequenced before relation, which extends naturally to threads. If two evaluations are not sequenced and one modifies a scalar object, the behaviour is undefined when the other reads or writes it (C17 6.5).
There is a sequence point:
- after the function designator and all arguments are evaluated, before the call;
- after the first operand of
&&,||,,and?:; - after each full expression, such as an expression statement, and the controlling
expression of
if,switch,while,doandfor; - after each full declarator;
- before a library function returns;
- after each conversion specifier in formatted input or output;
- around each call to a comparison function by
qsortorbsearch.
C11 also says the following are sequenced. The value computations of an operator’s operands
come before the value computation of its result. The side effect of an assignment comes after
the value computations of both operands. The value computation of postfix ++ and
-- comes before the side effect. Unsequenced function calls in the same expression
are indeterminately sequenced with respect to one another.
i = i++ + 1; /* undefined: two unsequenced modifications of i */
a[i] = i++; /* undefined: a read of i is unsequenced with the update */
f(i++, i++); /* undefined: arguments are unsequenced */
x = f() + g(); /* f and g may run in either order */
The operands of most operators, and the arguments of a function, may be evaluated in any order. Split such code into separate statements.