C++ Ripped Apart :: Section 1
Author: Mike Ware
Website: [warebiz] :: "The Programmer's Domain" - http://warebiz.tripod.com
Email: warebiz@yahoo.com
Copyright © 2003 Michael Shawn Ware, All Rights Reserved.


You are here --> [Section 1 :: C++ Basics]

"Jump To Articles"
    --> C++ Syntax
    --> Variables / Data Types
    --> Preprocessor Capabilities
    --> Arithmetic Operators & Assignment Statements
    --> Operator Precedence & Operator Associativity
    --> Type Conversion (Implicit Vs. Explicit)
    --> Logical Expressions


C++ Syntax

Understanding the syntax of C++, as well as all other languages, is extremely critical. By definition, syntax refers to the rules governing the formation of statements in a programming language. In other words, it is the specific language (code) programmers use to turn algorithms into programs and specific rules programmers must follow when programming. If a programmer makes one small syntax mistake when writing code, the compiler will catch the error and throw an alert during compilation. We will begin with a look at a simple example program written in C++.


///////////////////////////// BEGIN PROGRAM [using Dev-C++ V.4 Compiler] //////////////////////////////
// Program to calculate the average of 3 integers.
// Programmer: Mike Ware
// FILE: sec2-1.cpp
// Last Updated: 9/5/02

#include <iostream.h>    // header file for input/output stream
#include <stdlib.h>    // header file for standard input/output

int main( )
{
    int number1, number2, number3;    // declaration of variables
    float average;

    cout << "Enter first integer: ";
    cin >> number1;
    cout << "Enter second integer: ";
    cin >> number2;
    cout << "Enter third integer: ";
    cin >> number3;

    average = float(number1 + number2 + number3) / 3;    // calculates the average

    cout << "\n\nThe average of the three integers is: " << average << endl << endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}    // end main( )


///////////////////////////////////////////////////////////////////////////////////////////////////////

For now, notice how each executable statement in the program ends with a semi-colon. Every executable statement must always be terminated with a semi-colon, which signals that it is the end of the statement. Any code placed after ( // ) will not affect the code; ( // ) and ( /* (text here) */ ) are used for comments and documentation. Also notice that constant text is always enclosed in parentheses. Let's dig deep into the code to explain the logic behind certain statements.

cout - console output - It is simply letting the compiler know that something is being sent into the output stream (normally the screen).

<< - insertion operator - cout and the insertion operator go hand and hand; you must use it whenever you issue a cout command.

cin - console input - It is simply letting the compiler know that something is being sent into the input stream (normally into the memory of a computer).

>> - extraction operator - cin and the extraction operator go hand and hand; you must use it whenever you issue a cin command.

endl - end line - Basically the same as pressing the return key in a text editor; terminates the current line and drops down to the next line.

system("PAUSE") - basically specifically designed for Dev's compiler; simply pausing the system during execution of the program so the user can interact with the program through a separate screen module

EXIT_SUCCESS - error status code - defined in stdlib.h; this makes for more readable and descriptive code when compared to returning a value such as ( 0 ) at the end of a program.

Program Structure
A program is made up of one or more functions. A function is a subprogram that performs some specific task and perhaps returns a value to the statement that called (invoked) it. The one required function for all programs is main( ); it serves as the starting point for execution of a program. The main( ) function may then call other functions which may call other functions and so on. A problem is broken down into smaller pieces or logical steps by using functions. In turn, this allows program code to have fewer dependencies.

>>>>>>>>>
DEFINITION: function - a subprogram that performs some specific task and perhaps returns a value to the statement that called it.
<<<<<<<<<

The following is an outline of the structure of a C++ program in the order in which each of the segments occur:
    a) an "overview" of program (comments, documentation)
    b) #include statements / global declarations
    c) function prototypes [no prototype is required for the main( ) function]
    d) main( ) definition
    e) definitions of other functions

Documentation
The first part of every program should always contain detailed documentation describing key aspects of the program. It should include the program's overall purpose, the name of the programmer who wrote the code, the date the program was last updated, and any other information that you or other programmers may need to know in case you or someone else refers to the program code in the future. Comments can be inserted into program code in two ways:

    a) for single line comments, use: // comments here
        Any characters placed after ( // ) is considered to be a comment.
    b) for mult-line comments, use : /* comments here */
        Any characters placed between ( /* ) and ( */ ) are also considered comments.

#include Statements
The #include section holds C++ include files which basically allow particular C++ code to be compiled and executed along with the "main" program files. The include files are different for every compiler, but #include <iostream.h> and #include <stdlib.h> are normally required for most compilers. The include statements are installed with the compiler, and it is your responsibility to call upon a statement if you need it. You are also allowed to create include files, [see Creating User-Defined Header Files (Section 8)].

NOTE: The area after the #include statements but before the main( ) function is called the global area of program code.

Function Prototypes
Function prototypes are placed after the include statements. Every function, except main ( ), must have a function prototype, which is described in detail below.

main( )
The main( ) function is the starting point of execution in a C++ program. All other functions and program flow executable statements branch from the main( ) function definition.

Definitions of Other Functions
The use of functions in C++ is very important to learn. Just like everything else in C++, functions must be declared, and they have a specific form, which is as follows:

    return-type function_name ( parameter list )
    {
        statement(s)
    }

For now, focus on the form of functions because we haven't covered any information concerning return-types, variable names, or parameters. We will cover those aspects later.

The function heading is simply:

    return-type function_name( parameter list )

The function body is simply:

    {
        statement(s)
    }

The function definition is simply the function heading plus the function body (the full function).

A function prototype looks exactly the same as the function heading with the addition of a semi-colon at the end.

    return-type function_name( parameter list );

Function prototypes are placed after the include statements but before the main( ) function in a program. Remember that main( ) is the only function that doesn't need a prototype; prototypes provide function declarations and are required for all other functions. The following is an example of a function that accepts three integers passed as parameters and returns the average of the three values.


    int getAverage(int num1, int num2, int num3)
    {
        int average;
        average = (num1 + num2 + num3) / 3.0;
        return average;
    }    // end getAverage ( )

    OR WRITTEN AS:

    int getAverage(int num1, int num2, int num3)
    {
        return ((num1 + num2 + num3) / 3.0);
    }    // end getAverage ( )

The function broken down:

function return type: int
function name: getAverage
parameters: num1, num2, num3

The following is another example of a function. This function will accept a Fahrenheit temperature passed as a parameter and will convert the temperature into the equivalent Celsius temperature and then return the Celsius temperature back to the calling statement.


    float convertFahrToCelsius( float fahrTemp )
    {
        float celsiusTemp;
        celsiusTemp = ( fahrTemp - 32 ) / 1.8;
        return celsiusTemp;
    }    // end convertFahrToCelsius ( )

    OR WRITTEN AS:

    float convertFahrToCelsius( float fahrTemp )
    {
        return ((fahrTemp - 32) / 1.8);
    }    // end convertFahrToCelsius ( )

It is obvious that in order to use this function, we need a complete program. A program whose only purpose is to test one or more functions is usually called a driver program. A function prototype is needed because everything in C++ must be declared before you can use it. In other words, it tells the compiler the name of the function, the return data type, and the number, order, and type of parameters; these properties make up a function's signature. This is everything a compiler needs to determine if you are using a function properly.

In C++, literals are exactly what they are. They have no special internal meaning. A literal can be a number, a letter, or a string (group of letters). 17, 'a', "name", "mike", "c++", 452, -112, etc.

Identifiers are names you given to constants, variables, functions, etc. In C++, an identifier must begin with a letter or an underscore and further characters must be letters, underscores, or digits. Examples are STAR_TREK, THX792b4, FifthAvenue, etc.

You have now seen bits and pieces of a program written in C++. Read on further to learn more about variables and data types...

Variables / Data Types

Every program you write will work with some form of data, either numerical or character. Computers are capable of working with data through the use of variables. A variable is a modifiable value that has an associate internal memory location Variables have an associated memory location inside a computer, and their value can be modified. It is important to note that the memory location of a variable stays constant throughout program execution; its value can change, and the memory location allows the computer to "look up" the variable in order to manipulate it. For example, consider a program that will calculate the average of three numbers. In the program code you could have four variables: num1, num2, num3, and average. During execution of the program, the compiler will give each of the variables a memory location in the memory of the computer. If the variables are not set to a default value in the program, as they are placed into memory they will be assigned some type of garbage value until that value is changed during execution of the program.

In order to use a variable in a program, you must tell the computer which type of data it will store (using a declaration statement). The following is three basic C++ types: int, float, and char. int is used for whole numbers without decimal points, float is used for real numbers with decimal points, and char is used for keyboard character or letter values. When declaring variables, you will need to specify a data type. A declaration statement will let the compiler know what type of data it is going to be working with. In C++, data is either integral (integers and characters) or floating-point. Characters are considered integral because character values will eventually be converted into an ASCII, which is a system designed to associate character values with numerical values, value. There is also a bool type. Boolean types can be used when using logical data; when something can be either true or false. A result of 1 is considered true, and a result of 0 is considered false.

NOTE: For more information on ASCII (American Standard Code for Information Interchange), see the first section of the General Programming tutorial. [General Programming (section 1)]

There are several possible type sizes and for some of these data types there is a choice of unsigned or signed types. Signed simply means that the data can be negative or positive. Unsigned means the data will be strictly positive. In the following list, the sizes are representative only (compiler dependent).

char 1 byte -128 to 127
unsigned char 1 byte 0 to 255
int 2 bytes -32,768 to 32,767
unsigned int 2 bytes 0 to 65,535
long or (long int) 4 bytes -2,147,483,648 to 2,147,483,647
unsigned long 4 bytes 0 to 4,294,967,295
float 4 bytes 3.4 x 10^-38 to 3.4 x 10^38
double 8 bytes 1.7 x 10^-308 to 1.7 x 10^308
long double 10 bytes 3.4 x 10^-4932 to 3.4 x 10^4932


Note that integer values may be given in decimal, hexadecimal, or octal. Any value that begins with 0x or OX is a hexadecimal number. Any value that begins with 0 is octal. Also note that floating point values may be given in scientific notation. For example, the value 2.693 x 10^23 can be written as 2.693E+23.

Variable names must be begin with a letter, and then continue to be letters, digits, and underscores. Variable names should be very descriptive and relate to the data it stores. For example, suppose I need a variable to store the grade of a student in a class; a possible variable would be studentGrade. Descriptive names allow for easier program logic and easier updating routines, and they are critical when developing complex programs. C++'s standard library (preprocessor directives) defines variable names using an initial underscore so try to stay away from specifying identifiers beginning with an underscore. The following is a listing of valid and invalid variable names:

Valid
starTrek
math_first_stu
test1Score

Invalid
zook$     /* no dollar signs */
1dude     /* must begin with letter */
this Name     /* cannot contain spaces */

You must declare a variable before using it in a program. The form for declaring a variable is as follows:

    data-type identifier;

where data-type is a data type from the listing above and identifier is the name of the variable. The declaration statement simply defines the "type" of the variable and lets the compiler know the "type" of data it will be used to store. After declaration, the variable will hold a garbage value, an extreme value given by the computer system whose only use is to occupy memory storage until the variable is given a "true" value during program execution. For a few declaration examples, consider:

        int num1;
        float num2;
        char letter;

This code segment would declare num1 as being type int, num2 as being type float, and letter as being type char. From here on out in the program, num1 must be integer values, num2 must be floating point values, and letter must represent a single character value. Initialization is different from declaring because you declare the variable and also give it an initial value. The initialization statement form is as follows:

    data-type identifier = value;

where data-type is naturally one of the data types described above, identifier is the name of the variable, and value is the variable's initial value. For a few initialization examples, consider:

        int num1 = 123;
        float num2 = 56.78;
        char letter = 'a';

This code segment would define num1 as type int with an initial value of 123, num2 of type float with an initial value of 56.78, and letter of type char with an initial value of 'a'. All variable values can change during program execution.

You can also initialize a variable constant. The form for named constants is:

    const data-type identifier = value; (where value is a literal)

The initializing is the same except for the preceding const keyword. By defining a variable as const, the variable's value cannot change during program execution. If the program tries to change its value, an error will occur. Constants are commonly used when sharing same data for many different elements in a program. They also allow for easier program updating. For an example, consider:

    const int MAXSIZE = 450;

We have now covered variables and data types. Let's move on to learn how preprocessor statements add efficiency to programs. Read on for more...

Preprocessor Capabilities

The preprocessor provides for very efficient actions to take place before any program code is actually executed. Preprocessor statements are not considered to be actual C++ executable statements; therefore there is no need to terminate them with a semi-colon or even include an equal sign ( = ) which would otherwise be expected. They are also considered to be executed during compile run-time rather than during program run-time. The form of a preprocessor statement is as follows:

    #define variableName value

where variableName is the name given to the constant value, and value is the value assigned to variableName. The pound symbol ( # ) is a dead giveaway that it is a preprocessor statement. The above form is used to define symbolic constants in programs. Symbolic constants specify values which will not change during program execution. The basic idea of using symbolic constants is to give descriptive names to values (that never need to be manipulated) that are normally used many times throughout the program. In turn, this makes updating the value a of a constant very easy to accomplish in the future.

We have also used the preprocessor statement to "include" or "link" other C++ files through the use of an #include statement at the very beginning of a program. The #include preprocessor statement searches a specified number of directories in search of a "target" file to be "linked" along with the program. The #include statement provides a convenient way of using practical coding functions with programs without the need to write the code for each program; "include" the file containing the practical code and then use the needed functions. There are two forms for the #include statement:

    #include <file>
    #include "file"

The angle brackets form < > represent files that are normally created by compiler developers and only search for the file in directories specified in the computer options. The quotes " " form is used for user-defined header files and normally only searches for the file in the current working directory. For more about user-defined header files, [see Creating User-Defined Header Files (Section 8)].

For an example of how preprocessor statements can be used in programs, consider the following complete program:


//////////////////////////// CODE COMPILED USING DEV-C++/C V.4 COMPILER ////////////////////////////

// PURPOSE: Demonstrates the use of preprocessor definitions.
//          Calculates the cost of purchasing concert tickets based on
//          a constant ticket price. It prompts the user to enter his name
//          and desired amount of tickets and performs necessary
//          calculations. A report summary displaying the user's name
//          and balance is generated as output to screen.
//
//          FILE: sec2-2.cpp
//
//
// PROGRAMMER: Mike Ware
// DATE LAST UPDATED: 2-5-02

#include <stdlib.h>
#include <iostream.h>

#define MAXNAMELENGTH 25
#define TICKETCOST 32.50
#define SHOWINDEX 25
#define IGNORESTREAM 80

int main()
{
      char buyerName[MAXNAMELENGTH];
      int numOfTickets;
      float balance;

      cout << "Dave Matthews Band Concert #" << SHOWINDEX << endl << endl;
      cout << "Enter first name: ";
      cin.get(buyerName, MAXNAMELENGTH);
      cin.ignore(IGNORESTREAM, '\n');
      cout << "Enter desired number of tickets: ";
      cin >> numOfTickets;

      // calculate balance based on ticket price
      balance = numOfTickets * TICKETCOST;

      cout << setiosflags(ios::showpoint | ios::fixed);
      cout << setprecision(2);

      cout << endl << endl << "SUMMARY REPORT" << endl;
      cout << "-------------------------------------------------" << endl;
      cout << setw(5) << " "  << "NAME: " << buyerName << endl;
      cout << setw(5) << " "  << "BALANCE: $" << balance << endl;
      cout << "-------------------------------------------------" << endl;

      cout << endl << endl;
      system("PAUSE");
      return EXIT_SUCCESS;
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Read on to learn how to assign values to variables and manipulate data with arithmetic operators...

Arithmetic Operators & Assignment Statements

Because programming languages such as C++ solve problems by directly manipulating data, there must be operators to carry out necessary data operations for a particular algorithm. C++ has many operators and the following will describe assignment operators, extended and shorthand assignment operators, arithmetic operators, and miscellaneous "built-in" operators.

NOTE: An expression always has a value and consists of at least one operand and perhaps more than one operand combined with an operator. An operand is what the operator will act on. A statement is a command or instruction (executable statement) carried out by the computer's CPU (central processing unit). A program is ultimately a series of statements structured to achieve a goal or solve a problem.

Assignment Statements
An assignment statement is easy to understand. It is a way of assigning a value to a variable. It stores a value in the indicated location. The assignment operator ( = ) is used for assigning a value to a particular variable. The form of an assignment statement is:

    variable = value;

where variable is considered to be an "lvalue" and value is a constant, expression, value, or variable. An "lvalue" is a name or expression that identifies an object; in other words, an "lvalue" represents a storage location that contains some type of value. During assignment, variable is considered to be the operand since the assignment operator ( = ) will "copy" the contents of value and store the result in the "lvalue" variable. When using the assignment operator ( = ) , the expression will always be evaluated from right to left (right associative).

Arithmetic Operators
For arithmetic expressions, the fundamental operators are as follows:

    +,- (unary and binary forms: positive/negative; addition/subtraction)
    * (multiplication)
    / (division)
    % (modulus or MOD) ---> returns the integer remainder of a division (defined for integers only)

NOTE: / will result in an integer value if both operands are integers; otherwise, it will result in an floating point value.
NOTE: % is defined for integers only.

Examples:

        int x = 25;
        int y = 7;
        cout << x / y << endl;        ---> 3
        cout << x % y << endl;        ---> 4
        cout << y % x << endl;        ---> 7

NOTE: the only possible values for an expression of the form x % y are: 0,1,2,...,y - 1

The following are a few examples:

Example 1: Suppose a line is 76 inches long. Convert this line in dimensions of feet and inches.

    feet = 76 / 12;
    inches = 76 % 12

Example 2: Determine if a given integer is odd or even.

    number % 2 == 0
    if true ---> number is even
    if false ---> number is odd

Example 3: Determine if a given number is divisible by 3.

    number % 3 == 0
    if true ---> yes
    if false ---> no

NOTE: == is a relational operator which is discussed in later articles [see Logical Expressions]

Hopefully you can see how division and modulus can be used for solving problems. The following are some common errors that many beginning programmers experience when programming.

Common Errors:

1) x = 29 % 4.8;
ERROR: the compiler will display something along the lines of "invalid use of floating-point". Remember modulus is defined only for integers.

2) p + 7 = x + 3;
ERROR: the compiler will display something along the lines of "Lvalue required", which means the compiler must find a memory location when assigning values to a variable. In C and C++, = is an assignment operator; it does not imply equality.

Extended Assignment
The extended assignment statement involves using the assignment operator ( = ) and is used to assign a value to multiple variables during an executable statement. For example, consider:

    int x = y = i = a = 15;

The above statement would assign all variables in the statement the value of 15. Remember that when using the assignment op ( = ), the expression is always evaluated from right to left; in this case, a is assigned 15, i is assigned the value of a (15), y is assigned the value of i (15), and x is assigned the value of y (15). Extended assignments are always evaluated from right to left (right associative).

Shorthand Assignment Operators
C++ also has shorthand assignment operators or sometimes called compound assignment operators. In general,

    n += expression; --> implies n = n + (expression)
    n -= expression; --> implies n = n - (expression)
    n *= expression; --> implies n = n * (expression)
    n /= expression; --> implies n = n / (expression)
    n %= expression; --> implies n = n % (expression)

Misc. "Built-In" Operators
These are "built-in" operators used for misc. purposes.

    sizeof( argument ) --> returns the size in bytes of argument, which can be a variable or data type.

The increment operator, ++, adds 1 to a variable. The decrement operator, --, does the opposite and subtracts 1 from a variable.

Example:

    n = n + 1 is equivalent to n++ and ++n
    n = n - 1 is equivalent to n-- and --n

n++ and n-- are called post-increments, which mean they are performed after everything else in the statement. ++n and --n are called pre-increments, which mean they are performed before anything else in the statement.

Example:

    int x = 7;
    int y = 4;
    cout << x++ * --y << endl;        --> 21
    cout << x " | " << y << endl;         --> 8  |  3

n = n + 1    -->    n++    -->    ++n
n = n - 1    -->    n--    -->    --n

You now know how to use arithmetic operators and assignment statements, but exactly how these operations get evaluated by the computer. Read on to find out which operators have precedence over others...

Operator Precedence & Operator Associativity

Operator precedence (determines which expressions are evaluated before others in a statement) and operator associativity are both very important to understand. The best way to understand these concepts is to examine some examples.

Operator Precedence
General Overview:

    ( ) --> parentheses (high precedence)
    unary +, -
    *, /, %
    binary +, - (low precedence)

NOTE: To override the default precedence in a statement, use parentheses ( ) to group expressions that need to be evaluated before others.

Operator Associativity

Associativity may be left associative (left to right) or right associative (right to left). All arithmetic ops are left associative; assignment ops (+=, -=, *=, /=, %=, =) are right associative.

Examine the following examples:


Example 1:

    int a = 6, b = 5, c = 9;     cout << a + b * c; --> 6 + ( 5 * 9 ) = 51     cout << a * b % c; --> ( 6 * 5 ) % 9 = 3

Example 2:

    int a = b = c = d = 6 --> initializes a, b, c, and d to a value of 6

Example 3:

    x = y = 5;     a = 8;     b = 5     c = a * b / 3 + a / x;     cout << c; --> ( 8 * 5 ) / 3 + ( 8 / 5 ) = 13 + 1 = 14

    c = 9 + a % b;     cout << c; --> 12

    c = 10 / 3 * ( 2 + b )     cout << c; --> 10 / 3 * ( 7 ) = 3 * 7 = 21;

Example 4:

    17 / 2 / 3 - 125 % 5 --> ( ( 17 / 2 ) / 3 ) - ( 125 % 5 ) = 2

    2.5 * 6 + 3 / 2.0 --> 15.0 + 1.5 = 16.5     2.5 * ( 6 + 3 ) / 2.0 --> 22.5 / 2.0 = 11.25

Now that we have covered the precedence of operators and operator associativity, we can move on to something that occurs during assignment statements, sometimes without the programmer asking for it and sometimes by the programmer specifically asking for it. Read on for more about type conversions...

Type Conversion

When executing assignment statements and performing calculations, data types may be temporarily or permanently converted to other data types through something called type conversion. Implicit conversions take place without the programmer specifically asking for it. Conversions requested by the programmer are called explicit conversions. Implicit conversions cause trouble because the programmer can be unaware of what is actually happening during execution of the program until the code is tested thoroughly.

Implicit Conversion

>>>>>>>>>
DEFINITION: implicit conversion - type conversion that happens without the programmer specifically asking for it
<<<<<<<<<

It's pretty clear that programmers can run into problems because of implicit conversions. However, if you fully understand data types and how they are defined for certain arithmetic operators, you should be able to avoid them. For instance, if y and z are float, and a is int, when the statement z = a + y is executed, the value of a will be stored in a temporary memory location as float for use in the rest of the statement. Then, the addition is done (in float form) and finally, the result stored in z. During this statement, a was implicitly converted into float during the execution of the statement.

Another form of implicit conversion may take place during assignment, but not necessarily from a smaller type to a larger type.

Example:

    int a;
    float b = 3.5;
    float c = 5.0;
    int d = 2;
    a = b * c / d;
    cout << a << endl;        --> 8

What conversion took place in the above example? d was implicitly converted to 2.0 during b * c / d. The result of that arithmetic is 8.75, but a was declared int, so a was implicitly converted to 8 during the assignment statement.

Explicit Conversion

>>>>>>>>>
DEFINITION: explicit conversion - type conversion requested by the programmer; sometimes called typecasting
<<<<<<<<<

While programmers are unaware of implicit conversions, they completely control explicit conversions. Explicit conversions, or typecasting, come in handy as you will see in later problems. Typecasting can be easily accomplished and has two forms: ( type )variable or type( variable ) where type is whatever data type you choose and variable is the variable being typecasted. It simply takes the value of variable and converts it into the type specified.

Example 1:

    double d;
    int k;
    d = 12.78;
    k = ( int )d;        --> k = 12
    d = double( k );        --> d = 12.0

Example 2:

    int m = 10, n = 4, r;
    double q;
    q = m / n;        --> q = 2.0
    r = ( double )m / n;        --> 2

    r = m / n;        --> 2
    q = ( double)m / n        --> 2.5

We have now covered assignment statements, arithmetic ops, operator precedence, associativity, and type conversions (implicit/explicit). Read on for more information about logical and relational expressions...

Logical Expressions

Logical expressions, sometimes called boolean expressions, are expressions that return a value of true or false. A ( 1, or more generally any nonzero value ) is always associated with a true expression; a ( 0 ) is always associated with a false expression. There will be many times when you as a programmer will have to write code to handle certain (true/ false) situations. If an expression is true, then you will issue some command or execute a sequence of instructions. If an expression is false, then you will issue some other command or instruction. A relational expression is a special type of logical expression in which some type of comparison is performed. The relational operators are >, <, <=, >=, ==, and !=.

>>>>>>>>>
DEFINITION: logical expression - an expression that returns a value of either true ( 1 ) or false ( 0 ).
<<<<<<<<<

>>>>>>>>>
DEFINITION: relational expression - a special type of logical expression in which some type of comparison is performed.
<<<<<<<<<

    Relational Operators
    > : greater than
    < : less than
    >= : greater than or equal to
    <= : less than or equal to
    == : is equal to
    != : is not equal to

One of the biggest problems many beginning programmers have is distinguishing between ( = ) and ( == ). Experienced programmers can even run into problems with these two operators because it is very easy to mistype them when programming. ( = ) is an operator used for assignment purposes; it does not imply equality. ( == ) is a relational operator used to compare two values to see if they are equal; "is equal to". Be careful not to use ( = ) in relational expressions when ( == ) is needed.

Examples of relational expressions (also logical expressions):

    1- a < 2 * b - 7
    2- c != -1
    3- b > c + 4 * 7

A relational expression is always a logical expression. Logical expressions are either relational expressions or a combination of multiple relational expressions joined together by the logical operators: &&, ||, and !.

    Logical Operators
    && : logical and
    || : logical or
    ! : logical not

Example of a logical expression (not a relational expression):

(a < b) || ( b < c)

If a = 5, b = 3, and c = 10, the result of this expression is 1 (true).

A quick way to tell if an expression is logical but not relational is if one of the logical operators is being used.

Common Errors:

1) Using = (assignment operator) when == is needed.

2) Using an expression such as:

    midTerm || final == 'A'     which needs to be changed to    midTerm == 'A' || final == 'A'

3) Using an expression such as:

    a < b < c     which needs to be changed to    a < b && b < c

4) Using && when || is needed or vice versa:

Suppose a variable x is being used and x = -1 and x = -99 have special meaning:

    if (x != -1 || x != -99)     is wrong and needs to be changed to    if (x != -1 && x != -99)

In general, the operators have precedence (highest to lowest):

    A - arithmetic
    R - relational
    L - logical

NOTE: The only exception is logical not ( ! ), which is evaluated before arithmetic operators.

Specifically, the overall precedence for operators in this tutorial is:

    1 : !, +, - (unary)
    2 : *, /, %
    3 : +, - (binary)
    4 : <, <=, >, >=
    5 : ==, !=
    6 : &&
    7 : ||

Practical Use Example:

Suppose an insurance company offers a discount on automobile insurance for students who have no prior accidents and a GPA of 3.0 or above. What expression could be used to ask this?

    numAccidents == 0 && gpa >= 3.0

Most compilers also have a capability called short-circuit evaluation when evaluating logical expressions. This makes the evaluation of logical operations much faster and increases program efficiency. If a compound logical expression involves one expression that is false and an AND ( && ) operation is used, the entire expression must be false. If one expression is true and OR ( || ) is involved, the entire expression must be true.

With logical and relational expressions covered, it's time to see how program flow can be controlled using C++. Read on for more about the different control structures...

Move on to next set of topics: [Section 2] - Controlling Execution With Control Structures

Back to Top