Unary Operators

Unary operators appear before their operand and associate from right to left.

Syntax

unary-expression :
postfix-expression
++ unary-expression
–– unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )

unary-operator : one of
& * + – ~ !

Prefix Increment and Decrement Operators

The unary operators (++ and ––) are called “prefix” increment or decrement operators when the increment or decrement operators appear before the operand. Postfix increment and decrement has higher precedence than prefix increment and decrement operators. The operand must have integral, floating, or pointer type and must be a modifiable l-value expression (an expression without the const attribute). The result is not an l-value.

When the operator appears before its operand, the operand is incremented or decremented and its new value is the result of the expression.

An operand of integral or floating type is incremented or decremented by the integer value 1. The type of the result is the same as the operand type. An operand of pointer type is incremented or decremented by the size of the object it addresses. An incremented pointer points to the next object; a decremented pointer points to the previous object.

This example illustrates the unary decrement operator:

if( line[--i] != '\n' )

return;

In this example, the variable i is decremented before it is used as a subscript to line.

Indirection and Address-of Operators

The indirection operator (*) accesses a value indirectly, through a pointer. The operand must be a pointer value. The result of the operation is the value addressed by the operand; that is, the value at the address to which its operand points. The type of the result is the type that the operand addresses.

If the operand points to a function, the result is a function designator. If it points to a storage location, the result is an l-value designating the storage location.

If the pointer value is invalid, the result is undefined. The following list includes some of the most common conditions that invalidate a pointer value.

The pointer is a null pointer.

The pointer specifies the address of a local item that is not visible at the time of the reference.

The pointer specifies an address that is inappropriately aligned for the type of the object pointed to.

The pointer specifies an address not used by the executing program.

The address-of operator (&) gives the address of its operand. The operand of the address-of operator can be either a function designator or an l-value that designates an object that is not a bit field and is not declared with the register storage-class specifier.

The result of the address operation is a pointer to the operand. The type addressed by the pointer is the type of the operand.

The address-of operator can only be applied to variables with fundamental, structure, or union types that are declared at the file-scope level, or to subscripted array references. In these expressions, a constant expression that does not include the address-of operator can be added to or subtracted from the address expression.

The following examples use these declarations:

int *pa, x;

int a[20];

double d;

This statement uses the address-of operator.

pa = &a[5];

The address-of operator (&) takes the address of the sixth element of the array a. The result is stored in the pointer variable pa.

x = *pa;

The indirection operator (*) is used in this example to access the int value at the address stored in pa. The value is assigned to the integer variable x.

if( x == *&x )

printf( "True\n" );

This example prints the word True, demonstrating that the result of applying the indirection operator to the address of x is the same as x.

int roundup( void ); /* Function declaration */

int *proundup = roundup;

int *pround = &roundup;

Once the function roundup is declared, two pointers to roundup are declared and initialized. The first pointer, proundup, is initialized using only the name of the function, while the second, pround, uses the address-of operator in the initialization. The initializations are equivalent.

Unary Arithmetic Operators

The C unary plus, arithmetic-negation, complement, and logical-negation operators are discussed in the following list:

Operator Description

+ The unary plus operator preceding an expression in parentheses forces the grouping of the enclosed operations. It is used with expressions involving more than one associative or commutative binary operator. The operand must have arithmetic type. The result is the value of the operand. An integral operand undergoes integral promotion. The type of the result is the type of the promoted operand.
The arithmetic-negation operator produces the negative (two's complement) of its operand. The operand must be an integral or floating value. This operator performs the usual arithmetic conversions.
~ The bitwise-complement (or bitwise-NOT) operator produces the bitwise complement of its operand. The operand must be of integral type. This operator performs usual arithmetic conversions; the result has the type of the operand after conversion.
! The logical-negation (logical-NOT) operator produces the value 0 if its operand is true (nonzero) and the value 1 if its operand is false (0). The result has int type. The operand must be an integral, floating, or pointer value.

The following examples illustrate these operators:

short x = 987;

x = -x;

In the example above, the new value of x is the negative of 987, or –987.

unsigned short y = 0xAAAA;

y = ~y;

In this example, the new value assigned to y is the one's complement of the unsigned value 0xAAAA, or 0x5555.

if( !(x < y) )

If x is greater than or equal to y, the result of the expression is 1 (true). If x is less than y, the result is 0 (false).

The sizeof Operator

The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand. This operator allows you to avoid specifying machine-dependent data sizes in your programs.

Syntax

sizeof unary-expression sizeof ( type-name )

The operand is either an identifier that is a unary-expression, or a type-cast expression (that is, a type specifier enclosed in parentheses). The unary-expression cannot represent a bit-field object, an incomplete type, or a function designator. The result is an unsigned integral constant. The standard header STDDEF.H defines this type as size_t.

When you apply the sizeof operator to an array identifier, the result is the size of the entire array rather than the size of the pointer represented by the array identifier.

When you apply the sizeof operator to a structure or union type name, or to an identifier of structure or union type, the result is the number of bytes in the structure or union, including internal and trailing padding. This size may include internal and trailing padding used to align the members of the structure or union on memory boundaries. Thus, the result may not correspond to the size calculated by adding up the storage requirements of the individual members.

If an unsized array is the last element of a structure, the sizeof operator returns the size of the structure without the array.

buffer = calloc(100, sizeof (int) );

This example uses the sizeof operator to pass the size of an int, which varies among machines, as an argument to a run-time function named calloc. The value returned by the function is stored in buffer.

static char *strings[] ={

“this is string one”,

“this is string two”,

“this is string three”,

};

const int string_no = ( sizeof strings ) / ( sizeof strings[0] );

In this example, strings is an array of pointers to char. The number of pointers is the number of elements in the array, but is not specified. It is easy to determine the number of pointers by using the sizeof operator to calculate the number of elements in the array. The const integer value string_no is initialized to this number. Because it is a const value, string_no cannot be modified.