**Expression Subcontexts
· Classes of Expressions
· Class Conversions
· Type Conversions
· Promoting
· Balancing
· Assigning and Type Casting
· Changing Representations
· Pointer Arithmetic
· Reading Expressions
· Grouping
· Operator Summary
· Order of Evaluation
**

**Add Assign
· Add
· Address of
· Assignment
· Bitwise AND Assign
· Bitwise AND
· Bitwise Exclusive OR Assign
· Bitwise Exclusive OR
· Bitwise Inclusive OR Assign
· Bitwise Inclusive OR
· Bitwise NOT
· Comma
· Conditional
· Divide Assign
· Divide
· Equals
· Function Call
· Greater Than Or Equal
· Greater Than
· Indirection
· Left Shift Assign
· Left Shift
· Less Than Or Equal
· Less Than
· Logical AND
· Logical NOT
· Logical OR
·
· Multiply Assign
· Multiply
· Not Equals
· Plus
· Point at
· Postdecrement
· Postincrement
· Predecrement
· Preincrement
· Remainder Assign
· Remainder
· Right Shift Assign
· Right Shift
· Select
· sizeof
· Subscript
· Subtract Assign
· Subtract
· Type Cast
**

You write **expressions** to determine values, to alter values stored
in objects, and to call functions that perform input and output. In
fact, you express all computations in the program by writing expressions.

The translator itself must evaluate some of the expressions you write to determine properties of the program. The translator or the target environment must evaluate other expressions prior to program startup to determine the initial values stored in objects with static duration. The program evaluates the remaining expressions when it executes.

This document describes the different classes of expressions and the restrictions on each class. It presents the common rules for writing all expressions, determining their types, and computing their values. It also discusses the constraints on the flow of control through an expression.

Within a statement or declaration, every full expression that you write inhabits one of three contexts:

More generally, however, every full expression or subexpression
that you write inhabits one of four
**expression subcontexts**,
depending on its goal:

- an rvalue subcontext, which includes test and value contexts
- an lvalue subcontext
- a function-designator subcontext
- a side-effects subcontext

An **rvalue subcontext**
specifies a value that has an
object type other than an
array type.
You create an rvalue subcontext wherever
you need to specify a test or value to the translator,
determine an initial value prior to
program startup
or compute a value when the program executes.

An **lvalue subcontext**
designates an object, but its expression
can have either an object type or an incomplete type. You create an
lvalue subcontext wherever you need to access the value stored in
an object, alter the stored value, or determine the address of the
object. (If the type is incomplete, you can determine only the address
of the object.)

A **function-designator
subcontext** designates a function. Hence,
its expression has a function type. You create a function-designator
subcontext wherever you need to
call a function or determine its address.

A **side-effects
subcontext** specifies no value and designates
no object or function. Hence, its expression can have a
*void* type.
You create a side-effects subcontext when you need to cause only side
effects.

For example, consider the following code sequence:

void f(int); int x; f(x = 3);

In the last line:

`f`

is in a function-designator subcontext`x`

is in an lvalue subcontext`3`

and`x = 3`

are both in rvalue subcontexts`f(x = 3)`

is in a side-effects subcontext

Every expression that you write belongs to
one of several **expression classes**,
depending upon its form. Four of these classes are closely
associated with the four
expression subcontexts:

- An
**rvalue expression**has an object type other than an array type. - An
**lvalue expression**designates an object and has an object type or an incomplete type. - A
**function-designator expression**has a function type. - A
**void expression**has a*void*type.

The first two of these classes have a number of subclasses. For instance, an arbitrary rvalue expression can be evaluated only by the program when it executes. One connotation of the term ``rvalue expression'' is that you cannot write such an expression where the translator must be able to determine its value before the program executes. Four subclasses of rvalue expressions, however, have a value that the translator or the target environment can determine prior to program startup:

- an address constant expression
- an arithmetic constant expression
- an integer constant expression
- a #if expression

An **address constant
expression** specifies a value that has a
pointer type
and that the translator or target environment can determine prior to
program startup.
Therefore, the expression must not cause
side effects.
You must not write subexpressions with a
*void* type.
(You cannot write a
*function call,
assigning, or
comma operator,
except as part of the operand of a
sizeof operator.)
You write address constant expressions to specify
the initial values stored in objects of pointer type with
static duration.*

For example:

extern int first; static int *pf = &first;&first is address constant

An **arithmetic constant
expression** specifies a value that has an
arithmetic type
and that the translator or target environment can determine prior to
program startup.
Therefore, the expression must not cause
side effects.
You must write only subexpressions that have arithmetic type.
(You cannot write a
*function call,
assiging, or
comma operator,
except as part of the operand of a
sizeof operator.)
You write arithmetic constant expressions to specify the
initial values stored in objects of arithmetic type with
static duration.*

For example:

extern int counter = 0; static int flt_bits = 6 / 0.30103 + 0.5; static int ret_bytes = sizeof f();

An **integer constant
expression** specifies a value that has an
integer type and that
the translator can determine at the point in
the program where you write the expression.
The same restrictions apply as for
arithmetic constant
expressions. In addition, you must
write only subexpressions that have integer type.
You can, however, write a
floating-point constant
as the operand of an integer
*type cast* operator.
You write integer constant expressions to specify:

- the value associated with a
*case*label - the value of an enumeration constants
- the repetition count in an array decorationwithin a declarator
- the number of bits in a bitfield specification

For example:

extern int a[20], a_copy[sizeof a / sizeof a[0]]; enum {red = 1, green = 4, blue = 16} color;

A #if expression
specifies a value that can be determined by an
*if* or
*elif* directive.
After preprocessing replaces
all names within the expression, the same restrictions apply as for
integer constant
expressions.

For example:

#if __STDC__ && 32767 < INT_MAX

Lvalue expressions fall into one of four subclasses:

- an accessible lvalue expression
- a modifiable lvalue expression
- an array lvalue expression
- an incomplete non-array lvalue expression

An **accessible lvalue
expression** designates an object that has an
object type other than an
array type. Hence, you can access the
value stored in the object.

For example:

static const struct complex imag = {0, 1}; return (imag);imag is accessible lvalue

A **modifiable lvalue
expression** designates an object that has
object type other than an
array type
or a *const* type. Hence, you can alter
the value stored in the object.

For example:

static int next_no = 0; return ++next_no;next_no is modifiable lvalue

An **array lvalue
expression** designates an object that has an
array type. The type can be
incomplete.
You often write expressions that implicitly
convert an array lvalue expression to an
rvalue expression of a
pointer type.
You can also take the address of an array lvalue expression.
For example:

static int bmask[] = {1, 8, 2, 4}; int (*pb)[] = &bmask;&bmask is pointer to arrayy = arg & bmask[i];bmask is array lvaluescan_it(bmask);bmask becomes pointer to int

An **incomplete
non-array lvalue expression** designates an object that has a
*void* type or an
incomplete structure or union type.
You can only take the address of such an expression. For example:

extern struct who_knows rom; static struct who_knows *rom_base = &rom;

Many of the expression subclasses are proper subsets of other subclasses. In other cases, the translator can convert an expression of one class to another when the context demands it. The following diagram illustrates all classes and subclasses of expressions and how they relate. Each box denotes a different class or subclass. It contains a subset of all expressions that you can write. An unlabeled arrow connects each subset to its containing set.

For example, an
integer constant expression
is a subset of all
arithmetic constant
expressions, which in turn is a subset of all
rvalue expressions.
An incomplete
non-array lvalue expression is not a subset of any other.
A label on an arrow tells you that a conversion
occurs if you write an expression of one class where the context requires
a result of another class. For example,
an rvalue expression that you write in a
side-effects subcontext
becomes a *void* result by dropping the value
associated with the rvalue.

The translator can make four
**conversions**
to satisfy context:

- from rvalue expression to void expression
- from accessible lvalue expression to rvalue expression
- from array lvalue expression to rvalue expression
- from function-designator expression to rvalue expression

If you write an rvalue expression in a
side-effects subcontext,
the translator discards the value of the expression and converts it to a
*void* type.
For example:

int y; y = 3;rvalue y = 3 becomes void

If you write an
accessible lvalue expression
in an rvalue subcontext (such as a
test or
value context),
the translator accesses the value stored in the object
to determine the result. A
qualified type (*const*
or *volatile*) becomes its corresponding unqualified type. For
example:

const int x; int y; y = x;const int lvalue x becomes int rvalue

If you write an
array lvalue expression
in an rvalue subcontext,
the translator converts the type *array of T* to *pointer
to T.* The value of the expression is the address of the first element
of the array. For example:

int a[10], *pi; pi = a;array a becomes pointer rvalue

If you write a
function-designator
expression in an
rvalue subcontext,
the translator converts the type *function returning T* to *pointer
to function returning T.* The value of the expression is the address
of the function. For example:

int f(void); int (*pf)(void); pf = f;function f becomes pointer rvalue

Within several contexts the translator converts the type of a scalar expression (or subexpression). The conversions are called:

This section describes each of these conversions and the context in which it occurs. It also shows how the translator determines the value of the converted type from the value of the original type.

*Except when it is the operand of the
sizeof* operator, an
integer rvalue expression has one of four types:

*int**unsigned int**long**unsigned long*

When you write an expression in an
rvalue subcontext and the expression
has an integer type that is not one of these types, the translator
**promotes** its type. If all of the values representable in the
original type are also representable as type *int,* then the
promoted type is *int.* Otherwise, the promoted type is *unsigned
int.*

Thus, for *signed char, short,* and any *signed bitfield*
type, the promoted type is *int.* For each of the remaining integer
types (*char, unsigned char, unsigned short,* any plain *bitfield*
type, or any *unsigned bitfield* type), the effect of these rules
is to favor promoting to *int* wherever possible, but to promote
to *unsigned int* if necessary to preserve the original value
in all possible cases.

For example:

signed char ch; unsigned short us, f(char *, ...); f("%i%x", ch,ch becomes intus);us becomes int or unsigned int

When you write an infix operator that has two arithmetic rvalue
operands, the translator frequently determines the type of the result
by **balancing** the types of the two operands. To balance two
types, the translator applies the following rules to the promoted
types of the operands:

- Unless the two types are
*unsigned int*and*long,*the balanced type is the promoted type (of the two) that occurs later in the sequence:*int, unsigned int, long, unsigned long, float, double,*and*long double.* - If the two types are
*unsigned int*and*long*and the type*long*can represent all values of type*unsigned int,*the balanced type is*long.* - Otherwise, the balanced type is
*unsigned long.*

Each of the operands is converted to the balanced type, the arithmetic operation occurs between the now identical types, and the result of the operation has the balanced type. For example:

int i; long lo; double d; return ((i + lo)i becomes long+ d);(i + lo) becomes double

You store a value in an object by writing an expression that
contains an **assigning** operator. The assigning operators are
`=`

,
`*=`

,
`/=`

,
`%=`

,
`+=`

,
`-=`

,
`<<=`

,
`>>=`

```
,
```

`&=`

,
`^=`

, and
`|=`

.

```
```If the type of the aalue to be stored by an assigning operator is
compatible
with the type of the object, the program stores the
value unmodified. Otherwise, the translator determines the appropriate
conversion to perform before storing the new value.

You can also specify a type conversion by writing a
*type cast* operator.
You can specify any type conversion permitted for
an assigning operator, plus several other conversions between scalar
types.

The translator defines a number of conversions between scalar
types that you can specify by assigning or type casting. It does not
define all possible conversions, however:

- You can convert any
arithmetic
(integer or floating-point) type
to any other arithmetic type. The conversion preserves the original
value, wherever possible. Otherwise, the value changes
with the representation
as described later in this section.
- You can convert any
pointer type to an
integer type, but the
result is always
implementation
defined.
You cannot convert a pointer type to a
floating-point type.
- You can convert any integer type to any pointer type.
The value zero yields a
null pointer value.
Any nonzero value yields an implementation-defined
result. You cannot convert a floating-point type to a pointer type.
- You can convert any object pointer or pointer to incomplete
type to any other object pointer or pointer to incomplete type. The
result is implementation defined, however, unless the original pointer
is suitably aligned for use as the resultant pointer. You can safely
convert any such pointer to a pointer to a character type (or a
*pointer
to void*, which has the same repeesentation). You can use such a
pointer to character to access the first byte of the object as a character.
If you then convert that pointer to a type
compatible
with the original pointer, it will equal
the original pointer and you can use the pointer
to access the object. For example:

int i;
char *pc = (char *)&i; **valid type cast**
*(int *)pc = 3; **also valid**
if (*pc == *(int *)pc) **also valid**
printf("int stores l.s. byte first\n");

- You can convert a pointer to any
function type to a pointer
to any other function type. If you then convert that pointer to a
type compatible with the original pointer, it will equal the original
pointer and you can use the pointer to call the function. For example,
the following two type casts are both valid:

extern int sum(int, int);
void (*pv)(void) = (void (*)(void))∑
if (((int (*)(int, int))pv)(1, 2) == 3)
printf("sum was called properly\n");

The following table summarizes all possible
scalar conversions. Note that you can convert any scalar type to any
other scalar type by specifying no more than two conversions. In many
cases, however, at least one of the conversions is
implementation
defined.

**Pointer to
From: Arithmetic Incomplete Pointer to
To: Type or Object Function
Arithmetic** any to integer to integer
**Type** only only
**Pointer to** from integer any ---
**Incomplete or** only
**Object**
**Pointer to** from integer --- any
**Function** only

### Changing Representations

When you convert between any two arithmetic types, what happens
to the value depends on the number of bits used to represent the original
and final types. The following table summarizes
all possible conversions between arithmetic types.
The table assumes that:

- A signed integer value
`X`

occupying `N`

bits can
represent (at least) all integers in the open-ended interval
`(-2^(N-1), 2^(N-1))`

.
- An unsigned integer value
`X`

occupying `N`

bits can represent all integers in the half-open interval
`[0, 2^N)`

(and no others).
- A floating-point value
`X`

can be characterized as having
`N`

bits reserved for representing sign and magnitude, so it
can exactly represent (at least) all integers in the open-ended interval
`(-2^(N-1), 2^(N-1))`

.

**Conversion N < M N == M N > M**
signed integer discard m.s. same value same value
to M-N bits
signed integer (can overflow)
unsigned integer if (X < 2^(N-1)) if (X < 2^(N-1)) same value
to same value same value
signed integer else impl.-def. else impl.-def.
(can overflow) (can overflow)
floating-point if (|X| < 2^(N-1)) if (|X| < 2^(N-1)) if (|X| < 2^(N-1))
to trunc(X) trunc(X) trunc(X)
signed integer else impl.-def. else impl.-def. else impl.-def.
(can overflow) (can overflow) (can overflow)
signed integer if (0 <= X) if (0 <= X) if (0 <= X)
to X % 2^N same value same value
unsigned integer else impl.-def. else X + 2^N else X + 2^N
unsigned integer X % 2^N same value same value
to
unsigned integer
floating-point if (0 <= X < 2^N) if (0 <= X < 2^N) if (0 <= X < 2^N)
to trunc(X) trunc(X) trunc(X)
unsigned integer else impl.-def. else impl.-def. else impl.-def.
(can overflow) (can overflow) (can overflow)
signed integer keep sign, same value same value
to keep m.s.
floating-point N-1 bits
unsigned integer + sign, + sign, same value
to keep m.s. keep m.s.
floating-point N-1 bits N-1 bits
floating-point keep m.s. same value same value
to N-1 bits
floating-point (can overflow)

The table shows what happens when you convert an `M`

-bit
representation with value `X`

to an `N`

-bit representation,
for the three cases where `M`

is less than, equal to, or greater
than `N.`

The abbreviations used in this table are:

`impl.-def.`

--
implementation
defined
`m.s.`

-- most significant
`trunc(X)`

-- the integer part of `X`

,
truncated toward zero
`X % Y`

-- the non-negative remainder after dividing
`X`

by `Y`

### Pointer Arithmetic

You can add an integer to a value of type pointer to object.
If the value of the pointer is the address of an array element, then
adding one to the value yields the address of the next array element.
Thus, for a pointer `p`

to any object:

(char *)(p + 1) **is identical to** (char *)p + sizeof (*p)

If the value of `p`

is the address of the first element
in an array object, then `*(p + n)`

designates element number
`n`

(counting from zero).
If the value of `p`

is the address
of the last element in an array object, then `(p + 1)`

is a valid
address, even though `*(p + 1)`

is not an accessible lvalue.
You can perform pointer arithmetic on `(p + 1)`

just as you can
on the address of any of the elements of the array. If you form any
other address that does not designate an element of the array object
(by adding an integer to a pointer), the result is undefined.

## Reading Expressions

You compose an expression from one or more
terms and zero or more operators:

Each term has a well defined
type and
class. If an expression
consists of a single term without operators, then the type and class
of the expression are the type and class of the term.

Each operator requires one, two, or three
**operands**. An
operand is a subexpression that can itself (generally) contain additional
operators as well as terms. If you write an expression with one or
more terms and a single operator, then the terms must be the operands
of the operator. Each operator accepts operands with only certain
combinations of types and classes. The types and classes of the operands
determine the type and class of the expression containing the operator.

If you write an expression with one or more terms and two operators,
then the translator must determine which terms to
group with which operators.
You can enclose any subexpression in parentheses to make
clear that it groups as a single operand. Such parentheses have no
other effect than to control grouping. If you do not write such parentheses,
however, the translator applies a number of
precedence rules
to determine how the expression groups. Every expression you write
groups in only one way.

This section describes how to determine the type and class of
any term. Later sections in this documents explain the rules for grouping
operands in the presence of two or more operators, the effect of each
operator, what operands it accepts, and what result it produces.

A term takes one of several forms:

A **name**
in this context be declared as one of three entities:

- a function
- an object (possibly with
incomplete type)
- an enumeration
constant

For a function, the name is a
function-designator expression
with the declared type. For an object, the name is an
lvalue expression
with the declared type. For an enumeration constant, the name is an
rvalue expression with type *int.*
(You can write a
type definition or
tag in an expression only as part of a
type-name declaration
enclosed in parentheses, to make a
*type cast* operator, or as the operand of a
*sizeof* operator.)

If no declaration is visible for one of these entities and if
you write a left parenthesis immediately following the name,
then the translator
implicitly declares
the name in the current name space
as a *function returning int* without any argument information.

An integer constant is an
rvalue expression whose type
depends on the value, the base, and any suffix you write.
In all cases, the value
is the sequence of digits taken as a number to the specified base.
Each base and suffix combination determines a sequence of possible types.
The translator selects the earliest type
in the sequence that can represent the value
of the particular integer constant.

For a
**decimal integer constant**,
the sequences are:

- no suffix --
* int, long, unsigned long*
`U`

suffix -- *unsigned int, unsigned long*
`L`

suffix -- *long, unsigned long*
`UL`

suffix -- *unsigned long*

For an
**octal** or
**
hexadecimal integer constant**,
the sequences are:

- no suffix --
* int, unsigned int, long, unsigned long*
`U`

suffix -- *unsigned int, unsigned long*
`L`

suffix -- *long, unsigned long*
`UL`

suffix -- *unsigned long*

For example, if type *int* has a 16-bit representation:

70 070 0x70 **all type int**
7000U 070U 0x7000 **all type unsigned**
70000 070L 0x700L **all type long**

A
floating-point
constant is an
rvalue expression whose
type depends on any suffix you write:

- no suffix --
*double*
`F`

suffix -- *float*
`L`

suffix -- *long double*

Its **value**
is the integer plus fraction parts, taken as a decimal number,
times ten raised to the exponent part, taken as a signed decimal
number.

A
character constant is an
rvalue expression.
If you specify just one character in
the character constant, its type depends on any prefix you write:

- no prefix --
*int*
`L`

prefix -- the type `wchar_t`

promoted

Its **value**
is the code for the character you specify in the
target character set.
If you specify other than one character in a character constant,
the type and value are
implementation
defined.

A
**string literal** is an
lvalue expression whose type depends
on the number of characters you specify and any prefix you write:

- no prefix --
*array of char* with repetition count *N*
`L`

prefix --* array of* `wchar_t`

with repetition count *N*

*N* is one more than the number of characters you specify
when you write the string (for the terminating null character).
Its stored **value**
is the sequence of codes for the character(s) you specify in the
target character set, followed by the value zero. For example:

"hello" **type is array of 6 char**
L"hai" **type is array of 4 wchar_t**

The term
**sizeof** (*declaration*)

is an rvalue expression of type `size_t`

,
with value as described for that operator.

Any expression you write enclosed in
**parentheses** is a term whose
type, class, and value are the same as for the expression. Enclosing
an expression in parentheses has no effect other than to control grouping.

## Grouping

In the absence of parentheses, the translator **groups**
operators with operands in the following order:

1. The translator applies a **postfix operator**
immediately following a term before it applies any other operator.
It then applies any postfix operators to the right of that operator,
grouping from left to right.

2. The translator applies a **prefix operator**
immediately preceding a term and any postfix operators.
It then applies any prefix operators to the
left of that operator, grouping from right to left.

3. The translator applies **infix operators**
in descending order of precedence.
Operators at the same order of precedence group either from left to
right or from right to left, as indicated for the particular precedence
level.

The translator resolves two ambiguities by:

- always interpreting
`sizeof (`*declaration*)

as a term (never as the
*sizeof* operator followed by a
*type cast* operator)
- always interpreting a comma within a
function call argument
list as an argument expression separator (never as a
*comma* operator
within an argument expression).

In either case, you can use parentheses to obtain the alternate
grouping.

The following table shows all operators grouped by
**precedence** level in descending order.

Operator Notation Grouping
postincrement X++ from left to right
postdecrement X--
subscript X[Y]
function call X(Y)
select member X.Y
point at member X->Y
sizeof sizeof X from right to left
preincrement ++X
predecrement --X
address of &X
indirection *X
plus +X
minus -X
bitwise NOT ~X
logical NOT !X
type cast (*declaration*)X
multiply X * Y from left to right
divide X / Y
remainder X % Y
add X + Y from left to right
subtract X - Y
left shift X << Y from left to right
right shift X >> Y
less than X < Y from left to right
less than or equal X <= Y
greater than X > Y
greater than or equal X >= Y
equals X == Y from left to right
not equals X != Y
bitwise AND X & Y from left to right
bitwise exclusive OR X ^ Y from left to right
bitwise inclusive OR X | Y from left to right
logical AND X && Y from left to right
logical OR X || Y from left to right
conditional Z ? X : Y from right to left
assignment X = Y from right to left
multiply assign X *= Y
divide assign X /= Y
remainder assign X %= Y
add assign X += Y
subtract assign X -= Y
left shift assign X <<= Y
right shift assign X >>= Y
bitwise AND assign X &= Y
bitwise exclusive OR assign X ^= Y
bitwise inclusive OR assign X |= Y
comma X, Y from left to right

The table also shows
how operators group within a given precedence level.

For example:

y = m * x + b **is** y = ((m * x) + b)
*p++ = -x->y **is** (*(p++)) = (-(x->y))

## Operator Summary

This section describes every operator. It lists the operators
alphabetically by name, showing how to write each one with operands
`X`

, `Y`

, and `Z`

(as needed).
Following a description
of what the operator does is a table of all permissible combinations
of operand types and classes, with the type and class of the result
for each combination.

Some expressions produce a result that has an integer type that
varies among implementations. Each of these types has a type definition
that you can include in the program by including the standard header
`<stddef.h>`

.
The type definitions are:

`ptrdiff_t`

(which is the type of the
*subtract* operator
when its operands are both pointers to objects)
`size_t`

(which is the type of the
*sizeof* operator)
`wchar_t`

(which is the type of an element of a
wide-character
string literal)

You do not have to include these type definitions in the program
to use the *subtract* or *sizeof* operators, for example,
or to write wide-character string literals.

If the result of an operation cannot be represented by a value
of the result type, then an
**exceptional result** occurs:

**Overflow** is an exceptional result
where the value is too large to be represented by an
arithmetic type.
**Underflow** is an exceptional result
where the value is too small to be represented by a
floating-point type.
**Zero divide** is an exceptional result
where the result of dividing by zero has no well defined value.

If any form of exceptional result occurs,
the program behavior is undefined.

A type described below as
**Q qualified** is an optionally
qualified type. It can be:

- unqualified
*const* qualified
*volatile* qualified
*const* and *volatile* qualified

For pointer arithmetic, every object is considered an array
object (with perhaps only one element). If the array `a`

has
`N`

elements, then `a[N]`

is the element immediately beyond the array.

## Add Assign

`X += Y`

You write `X += Y`

to access the value stored in the object
designated by `X`

, add the value of `Y`

to the stored value, and store the new value back in the object.

**
Result X Y**
type of X arithmetic arithmetic
rvalue modifiable lvalue rvalue
type of X pointer to object integer
rvalue modifiable lvalue rvalue

## Add

`X + Y`

You write `X + Y`

to add the value of
`Y`

to the value of `X`

.
You can add an integer to a pointer value only if the
result is the address of an element within (or just beyond) the same
array object.

**
Result X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
type of X pointer to object integer
rvalue rvalue rvalue
type of Y integer pointer to object
rvalue rvalue rvalue

## Address of

`&X`

You write `&X`

to obtain the address of the function or
object designated by `X`

. You cannot obtain the address of an
object declared with storage class `register`

.

**
Result X**
pointer to T any object type T
rvalue except bitfield
lvalue
pointer to T incomplete type T
rvalue lvalue
pointer to T function type T
rvalue function designator

## Assignment

`X = Y`

You write `X = Y`

to store
the value of `Y`

in the object
designated by `X`

. If `Y`

is an lvalue expression (that is converted to
an rvalue expression to obtain its stored value),
then the object it designates either must have no bytes in common
with the object designated by `X`

or must overlap exactly, and
the objects must have compatible types.

**
Result X Y**
type of X arithmetic arithmetic
rvalue modifiable lvalue rvalue
type of X pointer, structure, or type of X
rvalue union type T rvalue
modifiable lvalue
type of X pointer to qualified T pointer to same or
rvalue modifiable lvalue less qualified type
compatible with T
rvalue
type of X pointer to void pointer to object
rvalue modifiable lvalue or incomplete type
rvalue
type of X pointer to object pointer to void
rvalue or incomplete type rvalue
modifiable lvalue
type of X any pointer type integer zero
rvalue modifiable lvalue rvalue

## Bitwise AND Assign

`X &= Y`

You write `X &= Y`

to access
the value stored in the object
designated by `X`

, form the
bitwise AND of the value
of `Y`

with the stored value,
and store the new value back in the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Bitwise AND

`X & Y`

You write `X & Y`

to form
the bitwise AND of the values of
`X`

and `Y`

. Each bit of the result
is set if the corresponding
bits in both `X`

and `Y`

are set.

**
Result X Y**
balanced type of X and Y integer integer
rvalue rvalue rvalue

## Bitwise Exclusive OR Assign

`X ^= Y`

You write `X ^= Y`

to access the value stored in the object
designated by `X`

, form the
bitwise exclusive OR of the value
of `Y`

with the stored value, and store the new value back in
the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Bitwise Exclusive OR

`X ^ Y`

You write `X ^ Y`

to form the bitwise exclusive OR of the
values of `X`

and `Y`

. Each bit of the result is set if
the corresponding bits in `X`

and `Y`

differ.

**
Result X Y**
balanced type of X and Y integer integer
rvalue rvalue rvalue

## Bitwise Inclusive OR Assign

`X |= Y`

You write `X |= Y`

to access the value stored in the object
designated by `X`

, form the
bitwise inclusive OR of the value
of `Y`

with the stored value, and store the new value back in
the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Bitwise Inclusive OR

`X | Y`

You write `X | Y`

to form the bitwise inclusive OR of the
values of `X`

and `Y`

. Each bit of the result is set if
either of the corresponding bits in
`X`

or `Y`

is set.

**
Result X Y**
balanced type of X and Y integer integer
rvalue rvalue rvalue

## Bitwise NOT

`~X`

You write `~X`

to form the bitwise NOT of the value of
`X`

. Each bit of the result is set if the corresponding bit in
`X`

is not set.

**
Result X**
type of X integer
rvalue rvalue

## Comma

`X, Y`

You write `X, Y`

to first evaluate `X`

as a
side-effects context
expression and then to evaluate `Y`

. There is a
sequence point
between the evaluation of the two operands.

**
Result X Y**
type of Y void expression any
rvalue rvalue

## Conditional

`Z ? X : Y`

You write `Z ? X : Y`

to evaluate
one of the operands `X`

or `Y`

,
depending on the value of the
test-context expression
`Z`

, which must be a scalar rvalue.
If `Z`

has a nonzero value,
then only `X`

is evaluated; otherwise, only `Y`

is
evaluated. The value of the expression is the value of the operand
that is evaluated, converted to the result type. A
sequence point
occurs between the evaluation of `Z`

and the evaluation of `X`

or `Y`

.

**
Result X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
type of X structure or union type of X
rvalue rvalue rvalue
type of X pointer to T integer zero
rvalue rvalue rvalue
type of Y integer zero pointer to T
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void void object or
rvalue rvalue incomplete type
rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void object or void
rvalue incomplete type rvalue
rvalue
void expression void expression void expression

## Divide Assign

`X /= Y`

You write `X /= Y`

to access the value stored in the object
designated by `X`

, divide that value by the value of `Y`

,
and store the new value back in the object. (See the *Divide*
operator following.)

**
Result X Y**
type of X arithmetic arithmetic
rvalue modifiable lvalue rvalue

## Divide

`X / Y`

You write `X / Y`

to divide the value of `X`

by the
value of `Y`

. Dividing by by zero yields an
exceptional result.
For integer types, a positive quotient truncates toward zero.

**
Result X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue

## Equals

`X == Y`

You write `X == Y`

to test whether the value of `X`

equals the value of `Y`

. The result is an *int* rvalue whose
value is 1 if the test is successful; otherwise, the value is zero.
Eachoof the operands is converted to a common test type for the comparison.
The table below shows the test type, rather than the result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
type of X pointer to T integer zero
rvalue rvalue rvalue
type of Y integer zero pointer to T
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void void object or
rvalue rvalue incomplete type
rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void object or void
rvalue incomplete type rvalue
rvalue

## Function Call

`X(Y)`

You write `X(Y)`

to call a function.
The value of the expression
(if any) is the value that the function returns. A
sequence point
occurs after the program evaluates `X`

and `Y`

and before it
calls the function.

**
Result X Y**
object type T function returning T zero or more
rvalue function designator argument rvalues
object type T pointer to function zero or more
rvalue returning T argument rvalues
rvalue
void expression function returnigg zero or more
void argument rvalues
function designator
void expression pointer to function zerooor more
returning void argument rvalues
rvalue

## Greater Than Or Equal

`X >= Y`

You write `X >= Y`

to test
whether the value of `X`

is greater than or equal to the value of `Y`

. The result is an
*int* rvalue whose value is 1 if the test is successful; otherwise,
the value is zero. Each of the operands is converted to a common test
type for the comparison. You can compare two pointer values only if
they are the addresses of elements within (or just beyond) the same
array object. The table below shows the test type, rather than the
result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue

## Greater Than

`X > Y`

You write `X > Y`

to test
whether the value of `X`

is
greater than the value of `Y`

. The result is an *int* rvalue
whose value is 1 if the test is successful; otherwise, the value is
zero. Each of the operands is converted to a common test type for
the comparison. You can compare two pointer values only if they are
the addresses of elements within (or just beyond) the same array object.
The table below shows the test type, rather than the result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue

## Indirection

`*X`

You write `*X`

to use the value of the pointer `X`

to designate an entity. The address of the entity is the value of
the pointer.

**
Result X**
type T pointer to object type T
lvalue rvalue
type T pointer to function type T
function designator rvalue
void expression pointer to void
rvalue

## Left Shift Assign

`X <<= Y`

You write `X <<= Y`

to access the value stored in the object
designated by `X`

,
shift that value to the left by the number
of bit positions specified by the value of `Y`

, and store the
new value back in the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Left Shift

`X << Y`

You write `X << Y`

to shift the value of `X`

to the
left by the number of bit positions
specified by the value of `Y`

.
For an `N`

-bit representation for the
promoted value of `X`

,
the value of `Y`

must be in the interval
`[0, N)`

. Zeros
fill the vacated bit positions.

**
Result X Y**
type of X integer integer
rvalue rvalue rvalue

## Less Than Or Equal

`X <= Y`

You write `X <= Y`

to test whether the value of `X`

is less than or equal to the value of `Y`

.
The result is an *int*
rvalue whose value is 1 if the test is successful; otherwise, the
value is zero. Each of the operands is converted to a common test
type for the comparison. You can compare two pointer values only if
they are the addresses of elements within (or just beyond) the same
array object. The table below shows the test type, rather than the
result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue

## Less Than

`X < Y`

You write `X < Y`

to test
whether the value of `X`

is
less than the value of `Y`

. The result is an *int* rvalue
whose value is 1 if the test is successful; otherwise, the value is
zero. Each of the operands is converted to a common test type for
the comparison. You can compare two pointer values only if they are
the addresses of elements within (or just beyond) the same array object.
The table below shows the test type, rather than the result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue

## Logical AND

`X && Y`

You write `X && Y`

to test whether both of the operands `X`

and `Y`

are nonzero. If `X`

is zero,
then only `X`

is evaluated and the value
of the expression is zero; otherwise, `Y`

is evaluated and the value of the expression is 1
if `Y`

is nonzero or zero if `Y`

is zero.
A sequence point occurs between the evaluation
of `X`

and the evaluation of `Y`

.

**
Result X Y**
int scalar scalar
rvalue rvalue rvalue

## Logical NOT

`!X`

You write `!X`

to test
whether `X`

is zero. If `X`

is zero, the value of the expression is 1; otherwise, the value is
zero.

**
Result X**
int scalar
rvalue rvalue

## Logical OR

`X || Y`

You write `X || Y`

to test whether either of the operands
`X`

or `Y`

is nonzero.
If `X`

has a nonzero value,
then only `X`

is evaluated and the value of the expression is
1; otherwise, `Y`

is evaluated and the value of the expression
is 1 if `Y`

is nonzero or zero if `Y`

is zero. A
sequence point
occurs between the evaluation of `X`

and the evaluation
of `Y`

.

**
Result X Y**
int scalar scalar
rvalue rvalue rvalue

`-X`

You write `-X`

to negate the value of `X`

.

**
Result X**
type of X arithmetic
rvalue rvalue

## Multiply Assign

`X *= Y`

You write `X *= Y`

to access the value stored in the object
designated by `X`

, multiply
that value by the value of `Y`

,
and store the new value back in the object.

**
Result X Y**
type of X arithmetic arithmetic
rvalue modifiable lvalue rvalue

## Multiply

You write `X * Y`

to multiply
the value of `X`

by the
value of `Y`

.

**
Result X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue

## Not Equals

`X != Y`

You write `X != Y`

to test whether the value of `X`

does not equal the value of `Y`

. The result is an *int*
rvalue whose value is 1 if the test is successful; otherwise, the
value is zero. Each of the operands is converted to a common test
type for the comparison. The table below shows the test type, rather
than the result type.

**
Test X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
type of X pointer to T integer zero
rvalue rvalue rvalue
type of Y integer zero pointer to T
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
composite of T and T' type T compatible type T'
rvalue rvalue rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void void object or
rvalue rvalue incomplete type
rvalue
pointer to pointer to pointer to
Q and Q' qualified Q qualified Q' qualified
void object or void
rvalue incomplete type rvalue
rvalue

## Plus

`+X`

You write `+X`

to leave
the value of `X`

unchanged.
(You use this operator primarily to emphasize
that a term is not negated.)

**
Result X**
type of X arithmetic
rvalue rvalue

## Point at

`X->Y`

You write `X->Y`

to select
the member whose name is `Y`

from the structure or union whose address
is the value of `X`

.

**
Result X Y**
type of member Y pointer to member name within
lvalue structure or union structure or union
rvalue

## Postdecrement

`X--`

You write `X--`

to access the value stored in the object
designated by `X`

, subtract 1 from the value, and store the new
value back in the object. The value of the expression is the *original*
value stored in the object.

**
Result X**
type T scalar type T
rvalue modifiable lvalue

## Postincrement

`X++`

You write `X++`

to access the value stored in the object
designated by `X`

, add 1 to the value, and store the new value
back in the object. The value of the expression is the *original*
value stored in the object.

**
Result X**
type T scalar type T
rvalue modifiable lvalue

## Predecrement

`--X`

You write `--X`

to access the value stored in the object
designated by `X`

, subtract 1 from the value, and store the new
value back in the object. The value of the expression is the *final*
value stored in the object.

**
Result X**
type T scalar type T
rvalue modifiable lvalue

## Preincrement

`++X`

You write `++X`

to access the value stored in the object
designated by `X`

, add 1 to the value, and store the new value
back in the object. The value of the expression is the *final*
value stored in the object.

**
Result X**
type T scalar type T
rvalue modifiable lvalue

## Remainder Assign

`X %= Y`

You write `X %= Y`

to access the value stored in the object
designated by `X`

, divide
that value by the value of `Y`

, and store the
remainder back in the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Remainder

`X % Y`

You write `X % Y`

to compute the remainder of the value of
`X`

divided by the value of `Y`

.
Dividing by by zero yields an
exceptional result.
Barring overflow or division by zero, it is always true that
`X = (X / Y) * Y + (X % Y)`

.

**
Result X Y**
balanced type of X and Y integer integer
rvalue rvalue rvalue

## Right Shift Assign

`X >>= Y`

You write `X >>= Y`

to access
the value stored in the object designated by `X`

,
shift that value to the right by the number
of bit positions specified by the value of `Y`

, and store the
new value back in the object.

**
Result X Y**
type of X integer integer
rvalue modifiable lvalue rvalue

## Right Shift

`X >> Y`

You write `X >> Y`

to shift the value of `X`

to the
right by the number of bit positions
specified by the value of `Y`

.
For an `N`

-bit representation
for the value of `X`

, the
(promoted) value of `Y`

must be in the interval
`[0, N)`

.
If `X`

is nonnegative, then zeros fill the vacated bit positions;
otherwise, the result is
implementation
defined.

**
Result X Y**
balanced type of X and Y integer integer
rvalue rvalue rvalue

## Select

`X.Y`

You write `X.Y`

to select the member `Y`

from the
structure or union `X`

. The result is an lvalue expression only
if `X`

is an lvalue expression.

**
Result X Y**
type of member Y structure or union member name within
lvalue lvalue the structure or union
type of member Y structure or union member name within
rvalue rvalue the structure or union

## sizeof

`sizeof X`

You write `sizeof X`

to determine the size in bytes of
an object whose type is the type of `X`

.
Do not write a function-designator expression for `X`

.
The translator uses the expression you write
for `X`

only to determine a type;
it is not evaluated. The operand `X`

is otherwise not considered a part of the expression containing
the *sizeof* operator. Therefore, prohibitions on what can be
in an expression (such as an arithmetic constant expression) do not
apply to any part of `X`

.

**
Result X**
size_t object type
rvalue lvalue
size_t object type
rvalue rvalue

## Subscript

`X[Y]`

You write `X[Y]`

to designate an array element. The operator
is identical in effect to `*((X)+(Y))`

.
Typically, `X`

is
an array lvalue expression (which becomes a pointer rvalue expression)
or an rvalue expression of some pointer type whose value is the address
of an array element. In this case, `Y`

is an integer rvalue.
The designated array element is `Y`

elements away from the element
designated by `X`

. Because of the symmetry of the two operands,
however, you can write them in either order.

**
Result X Y**
object type T pointer to T integer
lvalue rvalue rvalue
object type T integer pointer to T
lvalue rvalue rvalue

## Subtract Assign

`X -= Y`

You write `X -= Y`

to access the value stored in the object
designated by `X`

,
subtract the value of `Y`

from the value,
and store the new value back in the object.

**
Result X Y**
type of X arithmetic arithmetic
rvalue modifiable lvalue rvalue
type of X pointer to object integer
rvalue modifiable lvalue rvalue

## Subtract

`X - Y`

You write `X - Y`

to subtract the value of `Y`

from
the value of `X`

. You can subtract two pointer values only if
they are the addresses of elements within (or just beyond) the same
array object. The result tells you how many elements lie between the
two addresses.

**
Result X Y**
balanced type of X and Y arithmetic arithmetic
rvalue rvalue rvalue
type of X pointer to object integer
rvalue rvalue rvalue
ptrdiff_t pointer to Q qualified pointer to Q' qualified
rvalue object type T compatible type T'
rvalue rvalue

## Type Cast

`(`*decl*)X

You write `(`*decl*)X

to
convert the value of `X`

to the scalar (or *void*) type *T* that you specify in the
type-name declaration *decl*

enclosed in parentheses. The table
below shows valid combinations of declared type and operand type.

**
Result Type T X**
type T integer scalar
rvalue rvalue
type T floating-point arithmetic
rvalue rvalue
type T pointer to integer
rvalue any type rvalue
type T pointer to object pointer to object
rvalue or incomplete type or incomplete type
rvalue
type T pointer to pointer to
rvalue function function
rvalue
void expression void scalar rvalue or
void expression

## Order of Evaluation

When the program evaluates an expression, it has considerable
latitude in choosing the **order** in which it evaluates subexpressions.
For example, the translator can alter:

y = *p++;

either to:

temp = p; p += 1; y = *temp;

or to:

y = *p; p += 1;

As another example, the program can evaluate the expression

f() + g()

by calling the functions in either order.

The order of evaluation is important in understanding when
side effects occur,
such as storing a value in an object.

A **sequence point**
is a point in the program at which you
can determine which side effects have occurred and which have yet
to take place. Each of the expressions you write as part of a statement,
for example, has a sequence point at the end of it. You can be sure
that for:

y = 37;
x += y;

the program stores the value 37 in `y`

before it accesses
the value stored in `y`

to add it to the value stored in `x`

.

Sequence points can also occur within expressions. The
*comma,
conditional,
function call,
logical AND,* and
*logical OR*
operators each contain a sequence point. For example, you can write:

if ((c = getchar()) != EOF && isprint(c))

and know that the program evaluates `isprint(c)`

only after
a new value is stored in `c`

from the call to `getchar`

.

Between two sequence points, you must access the value stored
in an object whose contents you are altering only to determine the
new value to store, and store a value in an object no more than once.

For example:

val = 10 * val
+ (c - '0'); **well defined**
i = ++i + 2; **NOT well defined**

An expression can contain sequence points and still not have
a definite order of evaluation. In the example above, the expression
`f() + g()`

contains a sequence point before each function call,
but the *add* operator imposes no ordering on the evaluation
of its operands.

See also the
**Table of Contents** and the
**Index**.

*
Copyright © 1989-1996
by P.J. Plauger and Jim Brodie. All rights reserved.*