Operators & Expressions

Wednesday, 10 July 2013

Operators


C++ is rich in built-in operators. An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. C++ has three general classes of operators: arithmetic, relational and logical, and bitwise. In addition, C++ has some special operators for particular tasks. This chapter will examine the arithmetic, relational, and logical operators, reserving the more advanced bitwise operators for later.



Arithmetic Operators


Table 3-4 lists the arithmetic operators allowed in C++. The operators +, , *, and / all work the same way in C++ as they do in any other computer language (or algebra, for that matter). These can be applied to any built-in data type allowed by C++. When / is applied to an integer or a character, any remainder will be truncated; for example, 10/3 will equal 3 in integer division.



The modulus operator % also works in C++ in the same way that it does in other languages. Remember that the modulus operation yields the remainder of an integer division. This means that the%cannot be used on type float or double. The following program illustrates its use:
#include <iostream>
using namespace std;
int main()
{
int x, y;
x = 10;
y = 3;
cout << x/y; // will display 3
cout << "\n";
cout << x%y; /* will display 1, the remainder of
the integer division */
cout << "\n";
x = 1;
y = 2;
cout << x/y << " " << x%y; // will display 0 1
return 0;
}
The reason the last line prints a 0 and 1 is because 1/2 in integer division is 0, with a remainder of 1. Thus, 1%2 yields the remainder 1. The unary minus, in effect, multiplies its single operand by –1. That is, any number preceded by a minus sign switches its sign.

Increment and Decrement


C++ has two operators not found in some other computer languages. These are the increment and decrement operators, ++ and – –. These operators were mentioned in passing in Chapter 2, when the for loop was introduced. The ++ operator adds 1 to its operand, and – – subtracts 1. Therefore,
x = x+1;
is the same as
++x;
and
x = x-1;
is the same as
--x;
Both the increment and decrement operators can either precede (prefix) or follow (postfix) the operand. For example:
x = x+1;
can be written as
++x; // prefix form
or as
x++; // postfix form
In the foregoing example, there is no difference whether the increment is applied as a prefix or a postfix. However, when an increment or decrement is used as part of a larger expression, there is an important difference. When an increment or decrement operator precedes its operand, C++ will perform the corresponding operation prior to obtaining the operand’s value for use by the rest of the expression. If the operator follows its operand, then C++ will obtain the operand’s value before incrementing or decrementing it. Consider the following:
x = 10;
y = ++x;
In this case, y will be set to 11. However, if the code is written as
x = 10;
y = x++;
then y will be set to 10. In both cases, x is still set to 11; the difference is when it happens. There are significant advantages in being able to control when the increment or decrement operation takes place. Most C++ compilers create very fast, efficient object code for increment and decrement operations that is better than the code generated when the corresponding assignment
statement is used. Therefore, it is a good idea to use increment and decrement operators when you can. The precedence of the arithmetic operators is shown here:
highest ++ – –
(unary minus)
* / %
lowest + –
Operators on the same precedence level are evaluated by the compiler from left to right. Of course, parentheses may be used to alter the order of evaluation. Parentheses are treated by C++ in the same way that they are by virtually all other computer languages: They force an operation, or a set of operations, to have a higher precedence level.

How C++ Got Its Name


Now that you understand the full meaning behind the ++ operator, you can probably guess how C++ got its name. As you know, C++ is built upon the C language. C++ adds several enhancements to C, most of which support object-oriented programming. Thus, C++ represents an incremental improvement to C, making the addition of the ++ (the increment operator) to the name C a fitting name for C++. Bjarne Stroustrup initially named C++ “C with Classes.” However, at the suggestion of Rick Mascitti, Stroustrup later changed the name to C++. While the new language was already destined for success, the adoption of the name C++ virtually guaranteed its place in history because it was a name that every C programmer would instantly
recognize!

Relational and Logical Operators


In the terms relational operator and logical operator, relational refers to the relationships that values can have with one another, and logical refers to the ways in which true and false values can be connected together. Since the relational operators produce true or false results, they often work with the logical operators. For this reason, these operators will be discussed together here. The relational and logical operators are shown in Table 3-5. Notice that in C++, not equal is represented by != and equal is represented by the double equal sign, ==. In Standard C++, the outcome of a relational or logical expression produces a bool result. That is, the outcome of a relational or logical expression is either true or false. For older compilers, the outcome of a relational or logical expression will be an integer value of either 0 or 1. This difference is mostly academic, though, because C++ automatically converts true into 1 and false into 0, and vice versa. The operands for a relational operator can be of nearly any type, as long as they can be compared. The operands to the logical operators must produce a true or false result. Because any non-zero value is true and zero is false, the logical operators can be used with any expression that evaluates to a zero or non-zero result.
The logical operators are used to support the basic logical operations AND, OR, and NOT, according to the following truth table. The table uses 1 for true and 0 for false.

Although C++ does not contain a built-in exclusive-OR (XOR) logical operator, it is easy to construct one. The XOR operation uses this truth table:

In words, the XOR operation produces a true result when one, and only one, operand is true. The following function uses the && and || operators to construct an XOR operation. The result is returned by the function.
bool xor(bool a, bool b)
{
return (a || b) && !(a && b);
}
The following program uses this function. It displays the results of an AND, OR, and XOR on the values you enter. (Remember, one will be treated as true and zero is false.) // This program demonstrates the xor() function.
#include <iostream>
using namespace std;
bool xor(bool a, bool b);
int main()
{
bool p, q;
cout << "Enter P (0 or 1): ";
cin >> p;
cout << "Enter Q (0 or 1): ";
cin >> q;
cout << "P AND Q: " << (p && q) << '\n';
cout << "P OR Q: " << (p || q) << '\n';
cout << "P XOR Q: " << xor(p, q) << '\n';
return 0;
}
bool xor(bool a, bool b)
{
return (a || b) && !(a && b);
}
Here is a sample run produced by the program:
Enter P (0 or 1): 1
Enter Q (0 or 1): 1
P AND Q: 1
P OR Q: 1
P XOR Q: 0
In the program, notice that although the parameters to xor( ) are specified as type bool, integer values are entered by the user. As was just explained, this is allowed because C++ automatically converts 1 values into true and 0 into false. When the bool return value of xor( ) is output, it is automatically converted into either 1 or 0, depending upon whether the outcome of the operation is true or false. As a point of interest, it is also possible to specify the return type and parameters of xor ( ) as int, and the function would work exactly the same. Again, this is because of C++'s automatic conversions between integer values and Boolean values. Both the relational and logical operators are lower in precedence than the arithmetic operators. This means that an expression like 10 > 1+12 is evaluated as if it were written 10 > (1+12). The result is, of course, false. Also, the parentheses surrounding p && q and p || q in the preceding program are necessary because the && and || operators are lower in precedence than the output operator. You can link any number of relational operations together by using logical operators. For example, this expression joins three relational operations:
var>15 || !(10<count) && 3<=item.

Expressions


Operators, literals, and variables are constituents of expressions. You probably already know the general form of expressions from your other programming experience or from algebra. However, there are a few aspects of expressions that relate specifically to C++; these will be discussed now.

Type Conversion in Expressions


When literals and variables of different types are mixed in an expression, they are converted to the same type. First, all char and short int values are automatically elevated to int. This process is called integral promotion. Next, all operands are converted "up" to the type of the largest operand. This is called type promotion, and is done on an operation-by-operation basis. For example, if one operand is a int and the other a long int, then the int is promoted to long int. Or, if either operand is a double, the other operand is promoted to double. This means that conversions such as that from a char to a double are perfectly valid. Once a conversion has been applied, each pair of operands will be of the same type, and the result of each operation will be the same as the type of both operands. For example, consider the type conversions that occur in Figure 3-1. First, the character ch is promoted to int. Then the outcome of ch/i is converted to a double because f*d is a double. The final result is double because, by this time, both operands are double.

Converting to and from bool

As mentioned earlier, values of type bool are automatically converted into the integers 0 or 1 when used in an integer expression. When an integer result is converted to type bool, 0 becomes false and a non-zero value becomes true. Although bool is a fairly

recent addition to C++, the automatic conversions to and from integers mean that it has virtually no impact on older code. Furthermore, the automatic conversions allow C++ to maintain its original definition of true and false as zero and non-zero. Thus, bool is mostly a convenience to the programmer.

Casts


It is possible to force an expression to be of a specific type by using a construct called a cast. C++ defines five types of casts. Four allow detailed and sophisticated control over casting, and are described later in this book after objects have been explained. However, there is one type of cast that you can use now. It is C++’s most general cast because it can be used to transform any type into any other type. It was also the only type of cast that early versions of C++ supported. The general form of this cast is (type) expression where type is the target type into which you want to convert the expression. For example,\ if you want to make sure the expression x/2 is evaluated to type float, you can write (float) x / 2 Casts are often considered operators. As an operator, a cast is unary and has the same precedence as any other unary operator. There are times when a cast can be very useful. For example, you may want to use an integer for loop control, but also perform a computation on it that requires a fractional part, as in the program shown here:
#include <iostream>
using namespace std;
int main() // print i and i/2 with fractions
{
int i;
for(i=1; i<=100; ++i )
cout << i << "/ 2 is: " << (float) i / 2 << '\n';
return 0;
}
Without the cast (float) in this example, only an integer division would be performed. The cast ensures that the fractional part of the answer will be displayed on the screen.


Spacing and Parentheses


An expression in C++ may have tabs and spaces in it to make it more readable. For example, the following two expressions are the same, but the second is easier to read:
x=10/y*(127/x);
x = 10 / y * (127/x);
Use of redundant or additional parentheses will not cause errors or slow down them execution of the expression. You are encouraged to use parentheses to make clear the exact order of evaluation, both for yourself and for others who may have to figure out your program later. For example, which of the following two expressions is easier to read?
x = y/3-34*temp+127;
x = (y/3) - (34*temp) + 127;

No comments:

Post a Comment