Data Types

Wednesday, 10 July 2013

THE BASIC DATA TYPES:

All variables in C++ must be declared prior to their use. This is necessary because the compiler must know what type of data a variable contains before it can properly compile any statement that uses the variable. In C++ there are seven basic data types: character, wide character, integer, floating point, double floating point, Boolean, and somewhat surprisingly, valueless. The keywords used to declare variables of these types are char, chart, int, float, double, bool, and void, respectively. Common sizes and ranges of each data type are shown in Table 3-1. Remember, the sizes and ranges used by your compiler may vary from those listed here. The most common variance occurs between 16-bit and 32-bit environments. In general, an integer in a 16-bit environment is 16 bits wide. In a 32-bit environment, an integer is usually 32 bits wide Variables of type char are used to hold 8-bit ASCII characters such as A, B, or C, or any other 8-bit quantity. To specify a character, you must enclose it between single quotes. The type wchar_t is designed to hold characters that are part of large character sets. As you may know, many human languages, such as Chinese, define a large number of characters, more than will fit within the 8 bits provided by the char type.
The wchar_t type was added to C++ to accommodate this situation. While we won’t be making much use of wchar_t in this book, it is something that you will want to slook into if you are tailoring programs for the international market. Variables of type int can hold integer quantities that do not require fractional components. Variables of this type are often used for controlling loops and conditional statements. Variables of the types float and double are employed either when a fractional component is required or when your application requires very large or small numbers. The difference between a float and a double variable is the magnitude of the largest (and smallest) number that each one can hold. As shown in Table 3-1, a double in C++ can store a number approximately ten times larger than a float.

The bool type stores Boolean (i.e., true/false) values. C++ defines two Boolean constants: true and false, which are the only values that a bool variable may have. As you have seen, void is used to declare any function that does not return a value. Other purposes of void are discussed later in this book.

Declaration of Variables

The general form of a variable declaration statement is shown here:
type variable_list; Here, type must be a valid C++ data type, and variable_list may consist of one or more identifier names separated by commas. Some declarations are shown here, for example:
int i, j, k;
char ch, chr;ss
float f, balance;
double d;
In C++, the name of a variable has nothing to do with its type. Standard C++ states that at least the first 1,024 characters of any identifier name (including variable names) will be significant. This means that if two variable names differ in at least one character within the first 1,024 characters, then the compiler will consider them to be different names. There are three places where variables will be declared: inside functions, in the definition of function parameters, and outside of all functions. These variables are called local variables, formal parameters, and global variables, respectively. Although we will examine the importance of these three different types of variables in greater detail later in this book, let’s take a brief look at them now.

Local Variables

Variables that are declared inside a function are local variables. They can be used only
by statements that are inside that function. Local variables are not known to functions
Outside their own. Consider this example:
#include <iostream>
using namespace std;
void func();
int main()
{
int x; // local to main()
x = 10;
func();
cout << "\n";
cout << x; // displays 10
return 0;
}
void func()
{
int x; // local to func()
x = -199;
cout << x; // displays -199
}
Here, the integer variable x is declared twice, once in main( ) and once in func( ). The x in main( ) has no bearing on, or relationship to, the x in func( ). Specifically, changes to the x inside func( ) will not affect the x inside main( ). Therefore, this program will print –199 and 10 on the screen. In C++, local variables are created when the function is called and are destroyed when the function is exited. Correspondingly, the storage for these local variables is created and destroyed in the same way. For these reasons, local variables do not maintain\ their values between function calls. (That is, the value of a local variable is lost each time its function returns.) In some C++ literature, a local variable is called a dynamic variable or an automatic variable. However, this book will continue to use the term local variable because it is the more common term.

Formal Parameters


As you saw in Chapter 2, if a function has arguments, then those arguments must be declared. These are called the formal parameters of the function. As shown in the following fragment, this declaration occurs after the function name, inside the parentheses:
int func1(int first, int last, char ch)
{
.
.
.
}
The func1( ) function has three arguments, called first, last, and ch. You must tell C++ what type of variables these are by declaring them, as shown above. Once this has been done, these arguments receive information passed to the function. They may also be used inside the function as normal local variables. For example, you may make assignments to a function’s formal parameters or use them in any allowable C++ expression. Even though these variables perform the special task of receiving the value of the arguments passed to the function, they can be used like any other local variable. Like other local variables, their value is lost once the function terminates.

Global Variables


You may be wondering how to make a variable and its data stay in existence throughout the entire execution of your program. You can do this in C++ by using a global variable. Unlike local variables, global variables will hold their value throughout the lifetime of your program. You create global variables by declaring them outside of all functions. A global variable can be accessed by any function. That is, a global variable is available for use throughout your entire program. In the following program, you can see that the variable count has been declared outside of all functions. Its declaration is before the main( ) function. However, it could have been placed anywhere, as long as it was not in a function. Remember, though, that since you must declare a variable before you use it, it is best to declare global variables at the top of the program.
#include <iostream>
using namespace std;
void func1();
void func2();
int count; // this is a global variable
int main()
{
int i; // this is a local variable
for(i=0; i<10; i++) {
count = i * 2;
func1();
}
return 0;
}
void func1()
{
cout << "count: " << count; // access global count
cout << '\n'; // output a newline
func2();
}
void func2()
{
int count; // this is a local variable
for(count=0; count<3; count++) cout << '.';
}
Looking closely at this program, it should be clear that although neither main( ) nor func1( ) has declared the variable count, both may use it. In func2( ), however, a local variable called count is declared. When func2( ) uses count, it is referring to its local variable, not the global one. It is important to remember that if a global variable and a local variable have the same name, all references to that variable name inside the function in which the local variable is declared will refer to the local variable and not to the global variable.

Some Type Modifiers


C++ allows the char, int, and double data types to have modifiers preceding them. A modifier is used to alter the meaning of the base type so that it more precisely fits the needs of various situations. The data type modifiers are listed here:
signed
unsigned
long
short
The modifiers signed, unsigned, long, and short can be applied to integer base types. In addition, signed and unsigned can be applied to char, and long can be applied to double. Table’s 3-2a and 3-2b show all the allowed combinations of the basic types and the type modifiers for both 16- and 32-bit environments. The tables also show the most common size and range for each type. You should check your compiler’s documentation for the actual range supported by your compiler. As you look at the tables, pay special attention to the size of a short integer, an integer, and a long integer. Notice that in most 16-bit environments, the size of an integer is the same as a short integer. Also notice that in most 32-bit environments, the size of an integer is the same as a long integer. The reason for this is found in C++’s definition of its basic types. Standard C++ states that a long integer will be at least as large as an integer, and that an integer will be at least as large as a short integer. Further, the size of an integer should be based upon the execution environment. This means that for 16-bit environments, integers are 16 bits, and for 32-bit environments, integers are 32 bits. However, the smallest allowable size for an integer in any environment is 16 bits. Since C++ defines only the relationship and a set of guidelines for the size of the integer types, there is no requirement (or guarantee) that one type will be larger than another. However, the sizes shown in both tables hold true for many compilers.
Although it is allowed, the use of signed on integers is redundant because the default declaration assumes a signed value. Technically, whether char is signed or unsigned by default is implementation-defined. However, for most compilers, char is signed. In these environments, the use of signed on char is also redundant. For the rest of this book, it will be assumed that chars are signed entities. The difference between signed and unsigned integers is in the way the high-order bit of the integer is interpreted. If a signed integer is specified, then the C++ compiler will generate code that assumes that the high-order bit of an integer is to be used as a sign flag. If the sign flag is 0, then the number is positive; if it is 1, then the number is negative. Negative numbers are almost always represented using the two’s complement approach. In this method, all bits in the number are reversed, and then 1 is added to this number. Signed integers are important for a great many algorithms, but they have only half the absolute magnitude of their unsigned relatives. For example, assuming 16-bit integers, here is 32,767:
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
For a signed value, if the high-order bit were set to 1, the number would then be interpreted as –1 (assuming the two’s complement format). However, if you declared this to be an unsigned int, then when the high-order bit was set to 1, the number would become 65,535. To understand the difference between the way that signed and unsigned integers are interpreted by C++, you should run this short program now:
#include <iostream>
using namespace std;
/* This program shows the difference betweens
signed and unsigned integers.
*/
int main()
{
short int i; // a signed short integer
short unsigned int j; // an unsigned short integer
j = 60000;
i = j;
cout << i << " " << j;
return 0;
}
When this program is run, the output is –5536 60000. This is because the bit pattern that represents 60,000 as a short unsigned integer is interpreted as –5,536 by a short signed integer. C++ allows a shorthand notation for declaring unsigned, short, or long integers. You can simply use the word unsigned, short, or long, without the int. The int is implied. For example, the following two statements both declare unsigned integer variables.
unsigned x;
unsigned int y;
Variables of type char can be used to hold values other than just the ASCII character set. A char variable can also be used as a "small" integer with the range –128 through 127, and it can be used in place of an integer when the situation does not require larger numbers. For example, the following program uses a char variable to control the loop that prints the alphabet on the screen:
// This program prints the alphabet in reverse order.
#include <iostream>
using namespace std;
int main()
{
char letter;
for(letter = 'Z'; letter >= 'A'; letter--)
cout << letter;
return 0;
}
If the for loop seems weird to you, keep in mind that the character A is represented inside the computer as a number, and that the values from A to Z are sequential, in ascending order.

Literals


In C++, literals (also called constants) refer to fixed values that cannot be altered by the program. For the most part, literals and their usage are so intuitive that they have been used in one form or another by all the preceding sample programs. Now, the time has come to explain them formally.
C++ literals can be of any of the basic data types. The way each literal is represented depends upon its type. Character literals are enclosed between single quotes. For example, 'a' and '%' are both character literals. As some of the examples thus far have shown, if you want to assign a character to a variable of type char, you will use a statement similar to this one:
ch = 'Z';
To specify a wide character literal (i.e., one that is of type wchar_t), precede the character with an L. For example,
wchar_t wc;s
wc = L'A';
Here, wc is assigned the wide-character constant equivalent of A. Integer literals are specified as numbers without fractional components. For example, 10 and –100 are integer literals. Floating-point literals require the use of the decimal point, followed by the number’s fractional component. For example, 11.123 is a floating-point constant. C++ also allows you to use scientific notation for floating-point numbers.
There are two floating-point types: float and double. There are also several flavors of the basic types that can be generated with the type modifiers. The question is this: How does the compiler determine the type of a literal? For example, is 123.23 a float or a double? The answer to this question has two parts. First, the C++ compiler automatically makes certain assumptions about literals; second, you can explicitly specify the type of a literal, if you like. By default, the C++ compiler fits an integer literal into the smallest compatible data type that will hold it, beginning with int. Therefore, assuming 16-bit integers, 10 is int by default, but 103,000 is long. Even though the value 10 could be fit into a character, the compiler will not do this, because it means crossing type boundaries.
An exception to the smallest-type rule is a floating-point constant, which is assumed to be double. For virtually all programs you will write as a beginner, the compiler defaults are perfectly adequate. However, it is possible to specify precisely the type of literal you want. In cases where the default assumption that C++ makes about a numeric literal is not what you want, C++ allows you to specify the exact type by using a suffix. For floating point types, if you follow the number with an F, the number is treated as a float. If you follow it with an L, the number becomes a long double. For integer types, the U suffix stands for unsigned and the L for long. (Both the U and the L must be used to specify an unsigned long.) Some examples are shown here:

Variable Initializations


You can assign a value to a variable at the same time that it is declared by placing an equal sign and the value after the variable name. The general form of initialization is:
type variable_name = value;
Some examples are:
char ch = 'a';
int first = 0;
float balance = 123.23F;
Although variables are frequently initialized by constants, you can initialize a variable by using any expression valid at the time of the initialization. As you will see, initialization plays an important role when you are working with objects. Global variables are initialized only at the start of the program. Local variables are initialized each time the function in which they are declared is entered. All global variables are initialized to zero if no other initializer is specified. Local variables that are not initialized will have unknown values before the first assignment is made to them. Here is a simple example of variable initialization. This program uses the total ( ) function to compute the summation of the value that it is passed. In other words, total ( ) sums the digits from 1 to the value. For example, the summation of 3 is 1 + 2 + 3, or 6. In the process, total ( ) displays a running total. Notice the use of the sum variable in total ( ). // An example that uses variable initialization.
#include <iostream>
using namespace std;
void total(int x);
int main()
{
cout << "Computing summation of 5.\n";
total(5);
cout << "\n Computing summation of 6.\n";
total(6);
return 0;
}
void total(int x)
{
int sum=0; // initialize sum
int i, count;
for(i=1; i<=x; i++) {
sum = sum + i;
for(count=0; count<10; count++) cout << '.';
cout << "The current sum is " << sum << '\n';
}
}
Here is the output produced by the program.
Computing summation of 5.
..........The current sum is 1
..........The current sum is 3
..........The current sum is 6
..........The current sum is 10
..........The current sum is 15
Computing summation of 6.
..........The current sum is 1
..........The current sum is 3
..........The current sum is 6
..........The current sum is 10
..........The current sum is 15
..........The current sum is 21
As you can see, each time total( ) is called, sum is initialized to zero.

No comments:

Post a Comment