Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming Microcontrollers in C, 2-nd edit (Ted Van Sickle, 2001).pdf
Скачиваний:
296
Добавлен:
12.08.2013
Размер:
7.2 Mб
Скачать

24Chapter 1 Introduction to C

3.Write a program that reads the characters from an input file and counts in an array the occurrences of each letter. Make the pro­ gram “case insensitive” by treating all upper case letters as lower case.

Operators and Expressions

The variables and constants discussed in the previous section are classed as operands. They are values or objects that are operated upon by a program. The operations that take place are specified by operators. This section contains a discussion of the several opera­ tors.

Operators abound in C. All of the symbols involved in the lan­ guage are operators. Each has a precedence and an associativity. This section is concerned with how operators and operands are put to­ gether to interact in a manner desired by the programmer.

Arithmetic Operators

The arithmetic operators are those used to perform arithmetic operations. These operators are:

+

-

*

/

%

These operators are called binary operators because they are al­ ways used with two operands. These operands are placed on either side of the operator. The symbol + designates arithmetic addition, and the – symbol designates subtraction. The symbols * and / designate multiplication and division, respectively. These opera­ tors are clearly different for different variable types. The compiler understands these differences and creates correct code for the operand types involved. The modulus operator % returns the re­ mainder after an integer division. The modulus operator works only on integer types—-int, char, and long. It cannot be applied to types float, double or long double.

Operators and Expressions

25

 

 

Two unary operators are + and –. These operators are of higher precedence than the normal arithmetic operators. They operate on only the operand written to the right of the operator and are therefore called unary. The unary minus sign causes the negative value of the operand to be calculated, and the unary positive sign causes no cal­ culation to take place.

Among the binary operators, *, /, and % have equal prece­ dence, which is higher that of + and – . The unary operators + and – have a higher precedence than *, /, or %. The arithmetic operators will work with any of the arithmetic types. Because the operations needed for an integer operation differ from those needed for the cor­ responding double operation, the compiler will place the proper arithmetic routines in the code to perform the specified operation.

The concept of a fraction is almost unknown to an integer type. If a division of two integers is executed, the result is rounded toward zero. Therefore, the result of 1/2 is 0 as is 9999/10000. This charac­ teristic is often used in programming.

The only way that you can handle fractions with integer opera­ tions is to make use of the modulus operation. The result of a %b is the remainder that is left over after a is divided by b. The modulus operation can provide insight into the fractional value of what is left over after an integer divide.

EXERCISES

1.Write a program that evaluates f(x) = X 2 – 3X + 2

for values of X in 0 ≤ X ≤ 3 in steps of 0.1.

2.The roots of a quadratic equation can be evaluated by the equation

x = (–b + sqrt(b2 – 4ac))/2a

and

x = (–b – sqrt(b2 – 4ac))/2a

where the quadratic equation is ax2 + bx + c = 0. Write a pro­ gram that will evaluate the roots of such an equation. Note that the term sqrt(b2 - 4ac) is called the discriminant. If its argument

26 Chapter 1 Introduction to C

is not positive, the square root of a negative number is imaginary and the equation has complex roots. Handle both real and complex roots in your program.

Relational or Logical Operators

The relational operators are all binary operators. When contained in an expression, the program will evaluate the left operand and then the right operand. These operands will be compared, and if the com­ parison shows that the meaning of the operator is correct, the program will return 1. Otherwise, the program will return a 0. In the vocabu­ lary of C, FALSE is always zero. If calculated by a logical expression, TRUE will always be one. However, if the argument of a conditional expression is anything but zero, it will respond as if the argument is TRUE. In other words, FALSE is always zero and TRUE is anything else. The relational operators are:

<(less than)

<= (less than or equal to)

>(greater than)

>= (greater than or equal to)

These operators all have the same precedence, which is slightly higher than the following equality operators:

== (is equal to) != (is not equal to)

The logical operators are && and ||. The first operator indicates a logical AND and the second a logical OR. A logical AND will return TRUE if both of its operands are TRUE, and a logical OR will return TRUE if either of its operands is TRUE. The logical OR has lower precedence than the logical AND. The precedence of the logical AND is lower than the precedence of the relational operators and the equal­ ity operators.

In the evaluation of long logical expressions, the program starts on the left side of the expression and evaluates the expression until it knows whether the whole expression is true or false, and it then exits the evaluation and returns a proper value. For example, suppose there

Operators and Expressions

27

 

 

is a character c, and it is necessary to determine if this character is a letter. In such a case, the following logical expression might be used:

if( c >= ‘A’ && c <= ‘Z’ || c >= ‘a’ && c <= ‘z’)

The logical and operator && has lower precedence than any of the relational operators, so the relational expressions will each be evalu­ ated prior to the && operations. If upon entering this expression, c is equal to the character ‘5’, which is arithmetically smaller than any of the letters, the first term c >= ‘A’ will be FALSE. Therefore, the result of the first logical and expression is known to be FALSE without evaluating the term c <= ‘Z’. The evaluation will then skip to the third term c >= ‘a’, and the term c <= ‘Z’ will not be evaluated. In this case, the character ‘5’ will be smaller than the character ‘a’ so that the second and expression will also be FALSE. Therefore, the logical value will be known after evaluation of only two of the logical terms of the argument rather than having to evalu­ ate all four of the terms.

EXERCISES

1.Write a function that converts a character that is a letter to lower case.

2.Leap years occur every four years unless the year happens to be divisible by 100. Any year divisible by 400 is a leap year, however. Write a logical expression that will return TRUE if the given year is a leap year and FALSE if it is not.

Type Conversions Within Expressions

Implied in our earlier discussions on variable types, different data types not only occupy different width in memory, some may be com­ pletely incompatible when attempting to execute operations involving mixed data types. In earlier languages, it was up to the programmer to guarantee that the data types involved with an operation were the same. C resolves this problem, and the compiler will select the proper data type to complete operations on mixed data types.

Each data type has an implied width. When an operation is to be executed on mixed data types, the widths of the two types are evalu­ ated, and the lesser width operand is promoted to the type of the

28 Chapter 1 Introduction to C

greater width operand prior to execution of the operation. Thus, if the program called for d = a * b, where d is of type long, a is type int, and b is type long, a will be converted to the type long prior to the multiplication.

This logic carries over to mixing of float and double types as well. If for example a program called for the division a/b where a is of the type int and b is of the type double, the program would convert a to the type double before execution of the divide.

There might be times when the programmer will want to change the type of a variable. C provides a cast operator which forces the program to convert the type of a variable to a different type. This unary operator has the form.

(type name) expression

where the results of the evaluation of the expression will be con­ verted to the named type contained within the parentheses preceding the expression.

Bitwise Operators

Operators that work on the individual bits within a variable are called bitwise operators. Following is a table of all of these opera­ tors:

&

bitwise AND

>>

right shift

|

bitwise Inclusive OR

<<

left shift

^

bitwise Exclusive OR

~

one’s complement

The first three bitwise operators are traditional binary operators. These binary operators operate in integer type (char, int, long, etc.) operands, and the two operands must be of the same type.

If a bitwise AND is executed, those locations in the result where both operands have bit values of 1 will have a value of 1. All other locations will be 0. For a bitwise inclusive OR, each bit in the result will be 1 when either or both operand bits are 1. All locations where both operand bits are 0 will be 0. The exclusive OR is similar to an addition with no carry. Whenever the bits in the oper­ ands are different, the result bit will be 1. If both operand bits are the same, either both bits 1 or both bits 0, the result will be 0.

Operators and Expressions

29

 

 

The right shift operator and the left shift operator are also bi­ nary operators. Here the types of the operands need not be the same. The expression

x >> 3

causes the variable x to be shifted to the right by three bits prior to its use. Likewise,

y << 5

will cause y to be shifted to the left by five bits. In all number sys­ tems, a left shift by one digit corresponds to a multiplication by the number base. Similarly, a shift to the right by one digit causes a division by the number base. We are using the binary system in this case, so a shift left by one bit causes the number to be multiplied by two. Unlike most number systems, the binary system (or two’s complement system) allows the sign of the number to be contained in the binary representation of the number itself. These consider­ ations lead to two different types of shifts for a system of binary numbers. A shift in which bits vacated by the shift are replaced by zeros is called a logical shift. All left shifts are logical shifts. As the shift progresses toward the left, bits that fill the number from the right will all be zero. Bits that shift out of the number on the left side are lost. A right shift can be either a logical or an arithmetic shift. If the type being shifted is signed, the sign bit—which is the leftmost bit—will propagate, retaining a number of the same sign. This is an arithmetic sign. If the number being shifted is unsigned, zeros are filled into the number from the left as the shift proceeds. In all cases, bits shifted out of a number by a shift operation will be lost. The one’s complement operator ~ is a unary operator that causes the bits in a variable to be reversed. Every 1 is replaced by a 0, and every 0 is replaced by a 1. The bitwise AND and OR operations are used to turn bits on and off. Suppose that we have a character variable r, and we wish to turn the least significant three bits off. Try

r = r & ~7;

In this case, the number 7 has each of the least significant bits turned on or 1. Therefore, the term ~7 has all of the bits in the number but the least significant turned on and these three bits are turned off or 0.