Revised: February 3, 2007
By Richard G. Baldwin
File: Pf00160.htm
Practice Text
This lesson was written specifically for the benefit of my students in COSC 1315, Fundamentals of Programming. The lesson was written under the assumption that those students have no prior programming knowledge when they enroll in the course.
Another browser window
I recommend that you open another copy of this document in a separate browser window so that you can view the code and the discussion of that code at the same time.
Operators are the action elements of a computer program.
They perform actions such as:
Operands
Operators operate on operands.
For example, in the following expression, the plus character is an operator while x and y are operands.
x + y
Assuming that x and y are numeric primitive variables, this expression produces the sum of the values stored in the two variables.
The variable x would be called the left operand and the variable y would be called the right operand.
(An expression is a specific combination of operators and operands, which evaluates to a particular result.In your past experience, you may have referred to expressions by the names formulas or equations.The operands can be variables, literals, or method calls that return a value.)
Although formulas and equations are not exactly the same thing as expressions, they are close enough to help you understand what expressions are and how they are used.
Statements
A statement is a specific combination of expressions terminated by a semicolon.
The following is an example of a statement comprised of expressions.
z = x + y;
Operationally, in the above statement, values are retrieved from the variables named x and y. These two values are added together. The result is stored in (assigned to) the variable named z, replacing whatever value may previously have been contained in that variable.
C++ provides operators that can be used to perform an action on one, two, or three operands.
An operator that operates on one operand is called a unary operator.
An operator that operates on two operands is called a binary operator.
An operator that operates on three operands is called a ternary operator. (I believe that there is only one ternary operator in C++.)
Some operators can be either unary or binary
Some operators can behave either as a unary or as a binary operator.
(The best known operator that can behave either way is the minus sign.)
The minus sign as binary operator
As a binary operator, the minus sign causes its right operand to be subtracted from its left operand (provided that the two operands evaluate to numeric values).
For example, the following code subtracts the variable y from the variable x and assigns the result of the subtraction to the variable z. After the third statement is executed, the variable z contains the value 1.
int x = 6;
int y = 5;
int z = x - y;
The minus sign as unary operator
As a unary operator, the minus sign causes the algebraic sign of the right operand to be changed.
For example, the following two statements cause a value of -5 to be stored in the variable x.
int y = 5;
int x = -y;
Binary operators use infix notation
To keep you abreast of the jargon, binary operators in C++ use infix notation. This means that the operator appears between its operands.
Although I won't identify and discuss them in this lesson, there are also some unary operators that use prefix notation and unary operators that use postfix notation.
For prefix notation, the operator appears before (to the left of) its operand.
For postfix notation, the operator appears after (to the right of) its operand.
General behavior of an operator
As a result of performing the specified action, an operator can be said to return a value (or evaluate to a value) of a given type.
The type of value returned depends on the operator and on the types of the operands.
(To evaluate to a value means that after the action is performed, the operator and its operands are effectively replaced in the expression by the value that is returned.)
Operator categories
There are many different categories of operators that have different purposes. Microsoft identifies the following categories of C++ operators:
This lesson will not attempt to teach you about, or even to introduce you to all of the different C++ operators.
You will learn about many of the operators in due time if you continue to pursue an education in computer programming using C++, Java, or C#.
(While there are some differences in specific operators among these three object-oriented programming languages, to a large extent, all three languages use the same operators for the same or similar purposes.)
What you will learn in this course
In this course, you will mainly learn about the following operators. You will learn about the operators shown in boldface in this lesson. You will learn about many of the remaining operators in other lessons.
Have seen some operators before
You have already seen how some of these operators are used in previous lessons. For example, you first saw the use of the new operator, the Indirection operator, the Scope Resolution operator, and the Pointer-to-Member operator in the lesson entitled Basic Object-Based Program Structure.
You have seen the use of the Assignment operator in many previous lessons.
You saw the use of the Address-of operator and the Indirection operator in the lesson entitled C++ Variables and Constants.
You have seen the use of the Function call operator in several previous lessons including the lesson entitled C++ Functions.
The sample program in this lesson
I will provide and explain a simple program in this lesson that uses some of the Multiplicative and Additive operators as well as the Cast operator.
The lesson will also illustrate operator precedence.
In addition, this lesson will reinforce some of the operators that you have seen before.
A future lesson will explain the use of Relational and Equality operators as well as Logical operators in selection and loop structures.
The binary arithmetic operators
The following table lists the binary arithmetic operators supported by C++.
Operator Description + Adds its operands - Subtracts the right operand from the left operand * Multiplies the operands / Divides the left operand by the right operand % Remainder of dividing the left operand by the right operand - modulus operator |
Mixed data types
There are some subtle issues involved in the use of mixed data types with arithmetic operators.
Generally speaking, however, if you mix the integer types with the floating types, the integer values will be automatically converted to floating values and the arithmetic will be performed using floating arithmetic.
Floating arithmetic produces a floating result.
Integer division
If you perform integer division, the result will consist of only the whole-number part of the quotient.The remainder or fractional part will be discarded.
If you need the remainder, you can get it by using the modulus operator from the above table.
Precedence of operators
A very important issue has to do with the actual order in which operations are performed when two or more operators are used in the same expression.
For example, consider the following expression:
(2*a + 3)
Two ways to evaluate
There are two different ways that this expression could be evaluated:
Precedence table
Most programming languages provide a table from which you can determine the order of operations for any combination of operators. However, this table is often long and difficult to memorize.
After many years of programming, about all that I have memorized from the precedence table is that if you combine multiplication (or division) with addition (or subtraction), the multiplication (or division) will occur before the addition (or subtraction).
No need to memorize the precedence table
Fortunately, we don't need to memorize the precedence table.
We can always control the order of operations by grouping terms inside of pairs of matching parentheses.
For example, I could write the above expression in the following two ways:
(2*(a + 3))
((2*a) + 3)
Evaluate from inner-most outward
When you group terms in parentheses like this, the operations inside the inner-most pair of parentheses will be fully evaluated before removing those parentheses and beginning the evaluation within of the next-outer pair of parentheses.
For example, the first form shown above would add a to 3 and multiply the sum by 2.
The second form shown above would multiply a by 2 and add the product to 3.
The main point is ...
The main point is that whenever you are in doubt as to the order that the operations will take place in an expression, you can always control the order by the judicious use of pairs of matched parentheses.
If the parentheses are not needed, they will simply be discarded without causing any problems.
What is a cast operator?
For the moment, suffice it to say that the purpose of a cast operator is to force a conversion from one type to another.
In the sample program to be discussed later, a value of type char will be temporarily converted to type short using a cast operator to control how the value is displayed.
Description of the sample program
The C++ program that I will explain in this lesson illustrates expressions and operators. In particular, it illustrates the use of:
The program also illustrates the impact of operand types on the result of arithmetic operations.
I will discuss this program in fragments and show the output produced by each fragment. A complete listing of the program is provided in Listing 7.
The Scope Resolution operator
For several lessons, we have been using a global main function that uses the Scope Resolution operator to invoke a static function named classMain belonging to the class named Expressions01 (the name of the class differs from one lesson to the next).
Listing 1 shows the global main function and the use of the Scope Resolution operator for this purpose.
int main(){ //Note the use of the Scope Resolution // operator. Expressions01::classMain(); return 0; }//end main Listing 1 |
The Indirection, new, and Assignment operators
Also, for several lessons, we have been using a static function named classMain that uses the Indirection, new, Assignment and Pointer-to-Member operators to:
That code is shown in Listing 2.
class Expressions01{ public: static void classMain(){ //Instantiate an object in dynamic memory // and save its reference in a pointer // variable. Note the use of the Indirection // operator, the new operator, and the // Assignment operator. Expressions01* ptrToObject = new Expressions01(); //Invoke an instance function on the object. // Note the use of the Pointer-to-Member // operator. ptrToObject -> doSomething(); }//End classMain function Listing 2 |
The doSomething function
The doSomething function begins in Listing 3.
void doSomething(){ cout << "Precedence:\n"; cout << " 6*3+5 = " << 6*3+5 << endl; cout << " (6*3)+5 = " << (6*3)+5 << endl; cout << " 6*(3+5) = " << 6*(3+5) << endl; Listing 3 |
The code in Listing 3 illustrates the use of Multiplicative and Additive operators along with the use of parentheses to control the order in which the operations are performed. The output produced by the code in Listing 3 is shown in Figure 1.
Precedence: 6*3+5 = 23 (6*3)+5 = 23 6*(3+5) = 48 Figure 1 |
The order of the operations
The second line of output in Figure 1 shows the default case where multiplication is performed before addition.
The third line of output in Figure 1 shows that using a pair of parentheses to group the multiplicative terms has no effect since it simply reinforces the default behavior.
The fourth line of output in Figure 1 shows that using a pair of parentheses to group the additive terms has a major effect on the output. In this case, the expression inside the parentheses is evaluated first and the result of that evaluation (8) is multiplied by 6 producing a result of 48.
Effect of type on arithmetic results
The code in Listing 4 illustrates the effect of the type of operands on the result of arithmetic operations.
cout << "\nTypes of arithmetic" << endl; cout << " Float: 10.0/3.0 = " << 10.0/3.0 << endl; cout << " Mixed: 10.0/3 = " << 10.0/3 << endl; cout << " Integer: 10/3 = " << 10/3 << endl; Listing 4 |
The output produced by the code in Listing 4 is shown in Figure 2.
Types of arithmetic Float: 10.0/3.0 = 3.33333 Mixed: 10.0/3 = 3.33333 Integer: 10/3 = 3 Figure 2 |
Floating-point arithmetic
The second line of output in Figure 2 shows that when a floating-point value is divided by another floating-point value, the result is a floating-point value with the fractional part preserved.
Mixed type arithmetic
The third line of output in Figure 2 shows that when a floating-point value is divided by an integer value, the integer is automatically converted to a floating-point type. The result is a floating-point value with the fractional part preserved.
Integer arithmetic
The fourth line of output in Figure 2 shows that when an integer value is divided by another integer value, the result is also an integer value. Since an integer value doesn't have a fractional part, the fractional part of the result is simply discarded. This can often lead to logical errors, which produce incorrect results, and which are difficult to find and fix.
Getting a remainder
The code in Listing 5 illustrates the use of the modulus operator to get and display the remainder produced by an integer division.
cout << "\nThe modulus operator" << endl; cout << " For 11/3:\n"; cout << " Quotient = " << 11/3 << endl; cout << " Remainder = " << 11%3 << endl; Listing 5 |
An integer quotient
This code performs an integer division to get and display an integer quotient. In this case, the remainder or fractional part is simply discarded.
The remainder
Then the code in Listing 5 performs a modulus operation to get and display the remainder produced by the same integer division. In this case, the quotient is discarded.
The output produced by the code in Listing 5 is shown in Figure 3.
The modulus operator For 11/3: Quotient = 3 Remainder = 2 Figure 3 |
Using a cast operator to change type
We learned in an earlier lesson that when the insertion operator is used along with cout to display a variable of type char:
The code in Listing 6 uses a cast operator to force the numeric value of a variable of type char to be displayed.
cout << "\nThe cast operator" << endl; char var = 65; cout << " Display as type char: "<< var << endl; cout << " Display as type short: " << (short)var << endl; Listing 6 |
A temporary change of type
The code in Listing 6 uses a cast operator to temporarily change the type of data in a variable of type char to type short.
As a result, the insertion operator will treat it as type short and display the numeric value instead of the character represented by the numeric value.
The output produced by the code in Listing 6 is shown in Figure 4.
The cast operator Display as type char: A Display as type short: 65 Figure 4 |
A value of 65
As shown in Listing 6, a value of 65 is assigned to the variable of type char named var.
As shown by the second line of output in Figure 4, when this variable is displayed as type char, the value of 65 is automatically converted and displayed as an upper-case A.
(See the table at http://www.lookuptables.com/.)
When the cast operator is used to force the insertion operator to view the variable as type short, the actual numeric value stored in that variable is displayed.
A temporary change only
The use of a cast operator to change the type of the contents of a variable is temporary and lasts only for the duration of the evaluation of the expression in which the cast is performed.
There is no permanent change to the type of data stored in the variable.
In fact, it is not possible to permanently change the type of a variable.
Once a variable is declared to be of a given type, its type can never be changed thereafter.
A complete listing of the program is shown in Listing 7.
/*File: Expressions01.cpp This C++ program illustrates expressions and operators. In particular, it illustrates the use of: The Scope Resolution operator The Indirection operator The new operator The Assignment operator The Pointer-to-Member operator Multiplicative operators Additive operators Parenthesis to control precedence The modulus operator to get a remainder The cast operator to temporarily change the type of a value. The program also illustrates the impact of operand type on the result of an arithmetic operation. The program displays the following output on the screen: Precedence: 6*3+5 = 23 (6*3)+5 = 23 6*(3+5) = 48 Types of arithmetic Float: 10.0/3.0 = 3.33333 Mixed: 10.0/3 = 3.33333 Integer: 10/3 = 3 The modulus operator For 11/3: Quotient = 3 Remainder = 2 The cast operator Display as type char: A Display as type short: 65 Press any key to continue ************************************************/ #include <iostream> using namespace std; class Expressions01{ public: static void classMain(){ //Instantiate an object in dynamic memory // and save its reference in a pointer // variable. Note the use of the Indirection // operator, the new operator, and the // Assignment operator. Expressions01* ptrToObject = new Expressions01(); //Invoke an instance function on the object. // Note the use of the Pointer-to-Member, or // Member access operator. ptrToObject -> doSomething(); }//End classMain function //-------------------------------------------// //An instance function of the Expressions01 // class void doSomething(){ //Illustrate arithmetic operators and the use // of parentheses to control precedence. cout << "Precedence:\n"; cout << " 6*3+5 = " << 6*3+5 << endl; cout << " (6*3)+5 = " << (6*3)+5 << endl; cout << " 6*(3+5) = " << 6*(3+5) << endl; cout << "\nTypes of arithmetic" << endl; cout << " Float: 10.0/3.0 = " << 10.0/3.0 << endl; cout << " Mixed: 10.0/3 = " << 10.0/3 << endl; cout << " Integer: 10/3 = " << 10/3 << endl; //Illustrate the use of the modulus operator // to get a remainder. cout << "\nThe modulus operator" << endl; cout << " For 11/3:\n"; cout << " Quotient = " << 11/3 << endl; cout << " Remainder = " << 11%3 << endl; //Illustrate the use of the cast operator to // temporarily change the type of a value. cout << "\nThe cast operator" << endl; char var = 65; cout << " Display as type char: "<< var << endl; cout << " Display as type short: " << (short)var << endl; }//end doSomething function };//End Expressions01 class //---------------------------------------------// int main(){ //Note the use of the Scope Resolution // operator. Expressions01::classMain(); return 0; }//end main Listing 7 |
Copyright 2005, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.
In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP). His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments. (TI is still a world leader in DSP.) In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.
-end-