Ch 2: Dealing With Data - C++ by Metrowerks
Introduction to C++ by Metrowerks
Declaration of Variables and Type Modifiers
In Lesson 1, you were introduced to the programming language C++. After today's lesson, the programs you will be able to write will be more complex, and therefore, more valuable to you as a programmer. In today's lesson, we will study the different variable types and modifiers, and examine constants, operators, and expressions. All of the material you learn today will be used in our future lessons and will serve as the building blocks for all the programs you will write in the future.
A variable is the name associated with a value that can change throughout a program's execution. There are several different classifications of variables in C++. We call these classifications "types." These "types" relate to the specific kind of data contained in a variable. We will now discuss the different variable types and certain modifiers to these types.
Before a variable can be used in a C++ program, it must be declared. This declaration tells the compiler what type of data a variable will contain. There are 11 keywords used to declare variables:
|Declarers in parenthesis are optional
|bool||true false representation||1 or more|
|unsigned char||Character or numerical data||8|
|signed char||Character or numerical data||8|
|wchar_t||Wide character data||16|
|unsigned wchar_t||Wide character data||16|
|signed wchar_t||Wide character data||16|
|int||Whole number||16 or 32|
|unsigned int||Whole number||16 or 32|
|short (int)||Whole number||16|
|unsigned short||Whole number||16|
|long (int)||Whole number||32|
|unsigned long (int)||Whole number||32|
|long long (int)||Whole number||64|
|unsigned long long (int)||Whole number||64|
|float||Decimal fraction number||32|
|double||Decimal fraction number||64|
|long double||Decimal fraction number||64 or 128|
Table 2-1: Type Declaration Keywords.
|void||A valueless type||0|
The keywords are used in these combinations to form the predefined types.
The keyword for the first type of data we will declare is char. This declaration is used to hold 8-bit ASCII characters, such as X, Y or Z. A character is always specified within single quotation marks.
The keyword for the second data type, wchar_t, is a relatively new addition to C++. It is used to declare a "wide" character. Characters in languages like Chinese have a large number of bits per character -- more than the 8 bits per character allowed by the parameters of the char type. If you plan to write programs for the international market, wchar_t will be very useful.
The int type is used to hold integers -- whole numbers with no fractions or decimals. The int type is often used for variables that control conditional statements and loops.
float or double
When variables contain fractions, the types float and double may be used. A variable of the type double can hold about 10 times as many bits as a float variable. A float variable also has a minimal range of 6 digits of precision (after the decimal point), whereas a double has a minimum 10 digits of precision. Nevertheless, it is important to remember that all floating point type (real) numbers are defaulted to type double, not float.
Another relatively new addition to C++ is the bool type. A bool variable can only hold one of the two Boolean constants: true or false.
Finally, as we discussed in the previous lesson, a void type is used to declare a function that does not return a variable. We will discuss other uses of void in subsequent lessons.
Variables are declared in a declaration statement. This statement specifically names the type variable. Multiple variables of the same type can be declared in a single variable statement. To do this, just separate the variables with commas. Following are some examples of declaration statements:
int x, y, z;
char first_name, last_name;
float interest_rate, p;
In C++, the name of a unique variable can be up to 1,024 characters in length. Actually, C++ only recognizes the first 1,024 characters in a variable's name. Therefore, you can have two different variables that share 1,023 common characters, but the single dissimilar character will allow C++ to interpret them as different variables. Also, the first character must be a letter or an underscore, and subsequent characters must be either letters, digits, or underscores. For example, Count13 is valid, while 13Count is not. Furthermore, high_balance and sample13sample are perfectly valid, but high . . .balance and sample!sample are invalid.
Local Variables, Formal Parameters, and Global Variables
Variables can be declared either inside a function, in the definition of the function's parameters, or outside all functions. We'll briefly discuss each scenario here. The placement of variables will be covered in more depth later in the course.
Local variables are those that are declared inside a function. They can only be used within a function and are only recognized by the function in which they are declared. In the following program, the variable f has different values within each function.
using namespace std;
f = 100;
cout << "\n";
cout << f;
f = 50;
cout << f;
What will the output from this program look like?
The first output comes from the function testing(), in which f = 50. The second comes from the main() function, where f = 100.
In your assignment from Lesson 1, you read about functions with arguments. Arguments must be declared inside the parentheses after the function name. For example:
int testing2(int a, int b, int c)
ý. . .
The variables a, b, and c are arguments that receive information that is subsequently passed on to the function, since they are within the parentheses, they are used as local variables within the function testing2().
A variable that will be used throughout the program in several different functions is called a global variable. To give a variable a global scope, it must be declared outside of all functions in the program. The variable can be placed anywhere in the program as long as it is placed outside all functions. However, keep in mind that a variable must be declared before it can be used, so it is usually best to declare global variables before the main() function.
Remember: If a global variable and a local variable share a name, all references to that name within the function containing the local variable will reference the local variable, not the global variable. Let's take a look at a sample program to see this more clearly:
using namespace std;
v = 5;
cout << "\n";
cout << "\n";
v = v+5;
cout << v;
cout << v;
v = 20;
cout << v;
The output for the above program looks like this:
Notice that vtesting4(), is a local variable. The functions main() and testing3() reference the global variable v.
Constants, Access Modifiers, and Storage Class Specifiers
Now that you've learned the different kinds of variables and types, you will learn how to assign a static value to a variable and make other modifications to the way your variables behave.
Similar to the variable is the constant. A constant inputs a fixed value into an operation. After a discussion of constants, we will begin to explore C++ operators (symbols that take a value and yield results) and the basic structure of expressions.
Often, a program requires the use of a constant that cannot be changed by the operation of the program. A constant can be of any of the previously discussed data types. We will now discuss how to specify several different types of constants.
For the constant type, char, the character must be enclosed in single quotation marks. Following is an example of a constant specification:
character = 'A';
To specify a constant of type wchar_t, the specification is largely the same as above. However, the character must be preceded by an L:
character = L'A';
When specifying numerical constants, remember that the constant type is defaulted by the C++ compiler to the either a double (for real numbers) or int (for whole numbers) data type. Specification can be made to int, float, or long double.
One use for the const modifier is to set a single value that will be used (for example, if there are several arrays in your program that need to be the same size) throughout your program. Then, if you wish to change that value, you only need to make one change to your code. For example, look at the following
using namespace std;
const int arrsize = 5;
int arr1[arrsize], arr2[arrsize], arr3[arrsize];
// . . .
Should you wish to change the size of these three arrays to 7, only one change is necessary in the code.
We have previously used string constants in our sample program from Lesson 1. A string constant is a set of characters enclosed in double quotes. For example:
"Mary had a little lamb."
There is no true string constant type in C++. Later in the course, we will discuss the C++ class library, which contains a string type. Otherwise, C++ views a string as a character array. Do not confuse
The first is a character type. The second is a string constant with only one character. They are very different things in C++.
Escape Sequence Character Constants
The newline character (\n) was introduced in Lesson 1. We will now take a look at other backslash character constants. They are used in the same manner as the newline character:
|\N||octal constant where N is the octal constant|
Table 2-2: Backslash Character Constants.
|\xN||hexadecimal constant where N is the hexadecimal constant |
One of your assignments for this lesson will be to use these backslash character constants to create a program with a specified output. Make sure you are familiar with them before you attempt the assignment.
The volatile Modifier
Some variables are modified outside the program. For example, you may have a variable, clock, that is set by the computer's clock. This variable will be constantly changing. Therefore, whenever it is used in an operation, it should be updated before use. A declaration of volatile will ensure that the variable is retrieved from memory prior to each use. This also tells the compiler not to use any special optimizations on this volatile variable.
volatile int clock;
With the above declaration, clock's value will be obtained each time it is referenced.
Storage Class Specifiers
There are five storage class specifiers that determine how a variable is stored. These specifiers come first when declaring a variable. We will be looking at four of them now: auto, extern, register, and static.
The auto keyword is used to declare a local variable. The auto keyword is rarely used in a program because variables are auto by default.
In C++ programming, it is common to break the source code into two or more files. This separation will facilitate the compiling process after changes have been made to the program. Once this has been done, however, the problem of placing global variables arises. Global variables cannot be declared in each file because the program, when put together, will have multiple copies of each variable, and these duplications will cause problems with the compiler. There is a way to deal with this. Select a file and declare all of the global variables in that file. Then, copy the declarations to one common header file, but precede each declaration with extern. This tells the compiler to make the variables available throughout the entire program.
The effects of making a variable static differ for local and global variables. We will discuss these types of variables separately.
When a local variable is declared to be static, it requires permanent storage in the computer's memory, much like a global variable. However, its scope of use remains limited to the function or block in which it is declared. Another important effect a static declaration has on a local variable is that the variable, because it has permanent storage, is not re-initialized each time the block is called. Remember that a non-static local variable is created when an individual block of code is entered and destroyed when that block is exited.
If the static specifier is applied to a global variable within a certain file, it restricts the scope of that variable for that translation unit only. A translation unit is a file and all the headers or source files included in that file, either directly or indirectly. The variable will still act as a global variable within the translation unit in which it was declared -- it can be accessed by all functions within that translation unit. However, functions in other translation units will not be able to directly access or modify that variable.
When a variable is declared with the register specifier, the variable may be optimized for storage and retrieval. This specifier allows for faster access to the variable than would be available with regular storage. Only variables that are used frequently throughout the program should be declared with the register specifier. For small programs without extensive loops, the register specifier is not needed. When your programs become more complex and operational speed becomes an issue, the register specifier can come in handy.
An operator is a symbol that tells the compiler to perform a mathematical or logical manipulation. We will now examine the three classes of operators: arithmetic, relational, and logical.
The following are the arithmetic operators:
Table 2-3: Arithmetic Operators.
Some notes regarding these operators follow:
The modulus operator cannot be used on float or double types. The modulus operator enumerates any remainder that may result from the division of two integers.
When performing division on an int type, if the division does not render a whole-number quotient, the fractional remainder will be dropped. Therefore, using int types, if you divide 3 by 2, the operation will yield 1.
The following program shows how the modulus operator enumerates a remainder when two integers are divided.
using namespace std;
cout << "Enter the dividend: ";
cin >> d;
cout << "\nEnter the divisor: ";
cin >> r;
cout << d/r << " Remainder " << d%r;
Decrement and Increment
The ++ and -- operators are not found in many programming languages. However, they are quite important in the realm of C++. The ++ operator adds 1 to its operand and the --operator subtracts 1 from the operand. The following three statements will yield the same result:
Notice the last two statements. The second statement is written in a prefix form, while the third is written in the postfix form. While as written they have the same effect, they can be used in different ways. Take a look at the following example:
a = 5;
b = --a;
Compare this to:
a = 5;
b = a--;
In the first example, a has an ending value of 4 and b has an ending value of 4. The operation is performed on a first. Then, b is adjusted to the new value of a. In the second example, a still has an ending value of 4. However, b has an ending value of 5. In this operation, b is set to the value of a, then a is decremented.
As a side note, if there was a programming language, C, that was "incremented" to a much more powerful language, what would be a good name for that language? Right, C ++ !
Relational and Logical Operators
Relational operators compare the relationship of two values and result in a Boolean result (true or false). The relational operators are as follows:
|>=||greater than or equal to|
|<=||less than or equal to|
Table 2-4: Relational Operators.
|!=||not equal to|
Logical operators also result in Boolean results. Following are the logical operators:
Table 2-5: Relational and Logical Operators.
Because most expressions tend to follow the general rules of algebra (operator precedence and whatnot), they are often taken for granted. However, a few aspects of C++, such as type conversion, bool coversions, and spacing and parenthesis, relate specifically to C and C++.
Type Conversions in Expressions
When different variable types are used in a single expression, all smaller types within the expression are transformed to the largest variable type found in that expression. For example, if you create an expression with an int and a char, the char will be "upped" to an int, and the result of the expression will be in the form of an int. If this result is then used in an expression with a double variable, the int will be converted to a double and the result of the expression will be in the form of a double.
Values of type bool are converted to 0 for false and 1 for true.
Spacing and Parenthesis
When evaluating expressions, spaces are ignored in the execution of the program. They are used primarily to make expressions easier to read. The following two expressions would be interpreted by the compiler in exactly the same way:
a = 3 * b / (a + 67);
Parentheses can also be used to make expressions more readable. The following examples say exactly the same thing:
a = (b / 5) + (2 * a)
Namespaces allow you to protect areas of your code and avoid overlapping names for functions and variables.
Introduction to Namespaces
Namespace is a relatively new feature of the C++ language. Namespace is a means of identifying specific sections of code as unique. When you use that code, you need to specify the name of the space where that code is located. In standard C++, the library functions and symbols are written in the namespace 'std'. You may use namespaces indirectly by attaching the named space to an entire block of code in this manner:
using namespace std;
Or you may use namespaces directly, attaching the named space to the function or object in this manner.
This may not be clear right now, but over time it will be second nature. You'll find a more complete discussion of namespaces, and how to use them in your own programs in Lesson 12 of this course, and in Chapter 8 of
The C++ Primer Plus.
When you develop with Metrowerks CodeWarrior, you can use namespace within your code for the Metrowerks Standard Libraries. PowerPlant, the Macintosh framework included with CodeWarrior, also includes namespace that you may choose to use.