Unary expressions are formed by combining a unary operator with a single operand. All unary operators are of equal precedence and have right-to-left associativity. The unary operators are:
sizeof
operator (see Section 6.4.7)
Consider the following expression:
- expression
This is the negative of the operand. The operand must have
an arithmetic type, and integral promotion is applied. The
additive inverse of an unsigned
quantity is computed
by subtracting the quantity from the largest value of the
unsigned
type plus one.
The unary plus operator returns the value of an expression:
+ expression
Neither the unary plus nor unary minus operators produce lvalues.
Consider the following expression:
! expression
The result is the logical (Boolean) negation of the expression.
If the value of the expression is 0, the negated result is 1; if
the value of the expression is not 0, the negated result is 0. The
type of the result is int
. The expression must have a
scalar type.
C has two unary operators for incrementing and decrementing
scalar objects. The increment operator ++
adds 1
to its operand; the decrement operator -
subtracts
1. Both ++
and -
can be used either
as prefix operators (before the variable: ++n
) or
postfix operators (after the variable: n++
). In both
cases, the effect is to increment n
. The expression
++n
increments n
before its value is used,
while n++
increments n
after its value is
used.
Section 6.3.4 describes the postfix increment and decrement operators. This section describes the prefix form.
Consider the following expression:
++modifiable lvalue
After evaluating this expression, the result is the incremented rvalue, not the corresponding lvalue. For this reason, expressions that use the increment and decrement operators in this manner cannot appear by themselves on the left side of an assignment expression where an lvalue is needed.
If declared as an integer or floating-point number, the operand is increased or decreased by 1 (or 1.0). The results of the following C statements are equivalent:
i = i + 1; i++; ++i; i += 1;
The following example shows the difference between the postfix and prefix forms of the increment operator:
int i, j; j = 5; i = ++j; /* i = 6, j = 6 */ i = j++; /* i = 6, j = 7 */
If the operand is a pointer, the address is incremented by the size of the addressed object as determined by its data type, not by the integer value 1. For example:
char *cp; int *ip; ++cp; /* Incremented by sizeof(char) */ ++ip; /* Incremented by sizeof(int) */
Consider the following expression:
- - modifiable lvalue
The prefix operator -
is similar to the prefix operator
++
except that the value of the operand is decremented.
When using the increment and decrement operators, do not depend on the order of evaluation of expressions. Consider the following ambiguous expression:
k = x[j] + ++j;
It is unspecified whether the value of j
in
x[j]
is evaluated before or after j
is incremented. To avoid ambiguity, increment the variable in a
separate statement, as in the following example:
++j; k = x[j] + j;
Consider the following expression:
&lvalue
This expression results in the address of the lvalue. The lvalue can
be a function designator or any lvalue that designates an object,
including an unqualified array identifier. The lvalue cannot be a
register
variable or a bit field.
Consider the following expression:
*pointer
When an expression resolves to an address, the value stored at that address can be accessed by using the dereferencing operator (*).
If the operand of * is a function name or function pointer, then the result is a function designator. If the operand of * is a pointer to an object, then the result is an lvalue designating the object. If an invalid value (0, for example) is assigned to the pointer, then the * operation is undefined.
The dereferencing operator * always produces an lvalue. The address operator & never produces an lvalue.
Consider the following expression:
~ expression
The result is the bitwise negation (one's complement) of the evaluated expression. Each 1-bit is converted into a 0-bit and vice versa. The expression must have an integer type. The compiler performs the usual arithmetic conversions (see Section 6.10.1).
The cast operator forces the conversion of its scalar operand to a
specified scalar data type, or to void
. The operator
consists of a type-name, in parentheses, that precedes an
expression, as follows:
( type-name ) expression
The value of the expression is converted to the named data type, as if the expression were assigned to a variable of that type. The expression's type and value are not themselves changed; the value is converted to the cast type for the duration of the cast operation. The type-name has the following syntax:
type-specifier abstract-declarator
In simple cases, type-specifier is the keyword for a
data type, such as char
or double
, and
abstract-declarator is empty. For example:
(int)x;
The type-specifier can also be an enum
specifier, or a typedef
name. The type-
specifier can be a structure or union only if the abstract-
declarator is a pointer. That is, the type-name can
be a pointer to a structure or union, but cannot be a structure
or union because structures and unions are not scalar types. For
example:
(struct abc *)x /* allowed */ (struct abc)x /* not allowed */
The abstract-declarator in a cast operation is a declarator without an identifier. Abstract declarators have the following syntax:
empty abstract-declarator * abstract-declarator abstract-declarator ( ) abstract-declarator [ constant-expression ]
The abstract-declarator cannot be empty in the following form:
(abstract-declarator)
Abstract declarators can include the brackets and parentheses that
indicate arrays and functions. However, cast operations cannot force
the conversion of any expression to an array, function, structure,
or union. The brackets and parentheses are used in operations such
as the following example, which casts the identifier P1
to pointer to array of int
:
(int (*)[10]) P1;
This kind of cast operation does not change the contents of
P1
; it only causes the compiler to treat the value of
P1
as a pointer to such an array. For example, casting
pointers this way can change the scaling that occurs when an integer
is added to a pointer:
int *ip; ((char *)ip) + 1; /* Increments by 1 not by 4 */
Cast operators can be used in the following conversions that involve pointers:
int
or long
(or their
unsigned
equivalents). Therefore, a pointer can
be converted to any of these integer types and back again
without changing its value. No scaling takes place, and the
representation of the value does not change.
Converting from a pointer to a shorter integer type is similar to
converting from an unsigned long
type to a shorter
integer type; that is, the high-order bits of the pointer are
discarded.
Converting from a shorter integer type to a pointer is similar
to the conversion from a shorter integer type to an object of
unsigned long
type; that is, the high-order bits of
the pointer are filled with copies of the sign bit. DEC C, with the check option enabled, issues a
warning message for cast operations of this type.
Consider the syntax of the following expressions:
sizeof expression
sizeof ( type-name )
type-name cannot be an incomplete type, function type, or
a bit field. The sizeof
operator produces a compile-
time integer constant value. expression is inspected
only to deduce its type; it is not fully evaluated. For example,
sizeof(i++)
is equivalent to sizeof(i)
.
The result of the sizeof
operation is the size,
in bytes, of the operand. In the first case, the result of
sizeof
is the size determined by the type of the
expression. In the second case, the result is the size of an
object of the named type. The expression should be enclosed in
parentheses if it contains operators, because the precedence of
sizeof
is higher than that of most operators.
The syntax of type-name is the same as that for the cast operator. For example:
int x; x = sizeof(char *); /* assigns the size of a character pointer to x */
The type of the sizeof
operator's result, size_
t
, is an unsigned integer type. In DEC C, size_t
is unsigned
int
.