The operators in the productions below expect the first operand to identify an object, and modify its value.

unary-expression
++ unary-expression
Side-effects
-- unary-expression
Side-effects
postfix-expression
postfix-expression ++
Side-effects
postfix-expression --
Side-effects
assignment-expression
unary-expression assignment-operator assignment-expression
assignment-operator
=
*=
/=
%=
+=
-=
<<=
>>=
&=
^=
|=

Such a modification is called a side-effect, and it is the only way to modify the value of an object. An expression that identifies an object is an l-value, pronounced ‘el value’. If the object can be modified using that expression, the expression is a modifiable l-value. Operators with side-effects require the first operand to be a modifiable l-value.

Expressions are often useful for their side-effects alone, with the result being discarded. This happens most often in expression statements:

statement
expression-statement
expression-statement
expression ;

(Other places include the initializer and increment of a for loop, and the left operand of the comma operator (see expression).)

Given the following declarations:

int x;
int *xp = &x;
int arr[10] = { 0 }; // All zero

…here are a dozen or so expression statements with their side-effects explained:

// The l-value is a simple variable name.
x = 10;          // Set x to 10.
x++;             // Set x to 11.
x--;             // Set x to 10.
++x;             // Set x to 11.
--x;             // Set x to 10.

// The l-value identifies an object by dereferencing its address.
*xp = 6;         // Set x to 6.
(*xp)++;         // Set x to 7.
--*xp;           // Set x to 6.

// The l-value identifies an object in an array.
arr[3] = 10;     // Set arr[3] to 10.
++arr[4];        // Set arr[4] to 1.
arr[5]--;        // Set arr[5] to -1.
arr[x - 2] -= 3; // Set arr[4] to -2.

The operator ++ increments the object by one, while -- decrements by one. The simple assignment operator = assigns the value of its right operand to the object identified by the left operand. The operator -= decrements the object on the left by the value on the right. Other operators behave similarly, i.e., x op= y is equivalent to x = (x) op (y).

As expressions, all these operators yield a value, although it can be, and often is, ignored. The assignment operators yield the value that is assigned, permitting expressions such as x = y = z, which assigns the value of z to both x and y. The operators ++ and -- yield a value depending on whether the operand is to the left or right of the operator. ++x yields the new value of x; x++ yields the previous value of x.

Unmodifiable l-values are array names, and l-values of types qualified with const:

char arr[10];
const char *p = arr;
char *q;

arr = q;          // Error; arrays cannot be moved.

*(arr + 4) = 'c'; // Okay; arr + 4 has type char *.
arr[4] = 'c';     // Okay; same as above.

*(p + 4) = 'c';   // Error; p + 4 has type const char *.
p[4] = 'c';       // Error; same as above.

Although *(p + 4) identifies an object, and is therefore an l-value, p + 4 has type const char *, so *(p + 4) must have type const char, and that makes it unmodifiable.

Some expressions are used to invoke functions, and follow this grammar:

postfix-expression
postfix-expression ( argument-expression-listopt )

Depending on what it has access to, the invoked function may produce side-effects of its own.


CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000