IN THIS CHAPTER, you’ll look at some of the basic data types that are built into C++ and that you’re likely to use in all your programs. You’ll also investigate how to carry out simple numerical computations. All of C++’s objectoriented capability is founded on the basic data types built into the language, because all the data types that you’ll create are ultimately defined in terms of the basic types. It’s therefore important to get a good grasp of using them. By the end of the chapter, you’ll be able to write a simple C++ pro gram of the traditional form: input – process – output.
In this chapter, you’ll learn about
 Data types in C++
 What literals are and how you define them in a program
 Binary and hexadecimal representation for integers
 How you declare and initialize variables in your program
 How calculations using integers work
 Programming with values that aren’t integers—that is, floatingpoint calculations
 How you can prevent the value stored in a variable from being modified
 How to create variables that can store characters
Data and Data Types
C++ is a strongly typed language. In other words, every data item in your program has a type associated with it that defines what it is and your C++ compiler will make extensive checks to ensure that, as far as possible, you use the right data type in any given context and that when you combine different types, they’re made to be compatible. Because of this type checking, the compiler is able to detect and report most errors that would arise from the accidental interpretation of one type of data as another or from attempts to combine data items of types that are mutually incompatible.
The numeical values that you can work with in C++ fall into two broad categories: integers (in other words, whole numbers) and floatingpoint values, which can be fractional. You can’t conclude from this that there are just two numerical data types, however. There are actually several data types in each of these categories, and each type has its own permitted range of values that it can store. Before I get into numerical types in detail, let’s look at how you carry out arithmetic calculations in C++, starting with how you can calculate using integers.
{mospagebreak title=Performing Simple Calculations}To begin with, let’s get some bits of terminology out of the way. An operation (such as a mathematical calculation) is defined by an operator— + for addition, for example, or * for multiplication. The values that an operator acts upon are called operands, so in an expression such as 2*3 , the operands are 2 and 3 .
+ for addition, for example, or * for multiplication. The values that an operator acts upon are called , so in an expression such as 2*3 , the operands are 2 and 3 . To begin with, let’s get some bits of terminology out of the way. An operation (such as a mathematical calculation) is defined by an — + for addition, for example, or * for multiplication. The values that an operator acts upon are called , so in an expression such as 2*3, the operands are 2 and 3.Because the multiplication operator requires two operands, it is called a binary operator. Some other operators only require one operand, and these are called unary operators. An example of a unary operator is the minus sign in –2 . The minus sign acts on one operand—the value 2—and changes its sign. This contrasts with the binary subtraction operator in expressions such as 4 – 2 , which acts on two operands, the 4 and the 2 .
Introducing LiteralsIn C++, fixed values of any kind, such as 42 , or 2.71828 , or “Mark Twain” , are referred to as literals.In Chapter 1, when you were outputting text strings to the screen, you used a string literal—a constant defined by a series of characters between a pair of double quotes, of which “Mark Twain” is an example. Now you’ll investigate the types of literals that are numeric constants. These are the ordinary numbers you meet every day: your shoe size, the boiling point of lead, the number of angels that can sit on a pin—in fact, any defined number.
There are two broad classifications of numeric constants that you can use in C++:
 Integer literals are whole numbers and are written without a decimal point.
 Floatingpoint literals (commonly referred to as floatingpoint numbers) are numbers that can be nonintegral values and are always written with a decimal point, or an exponent, or both. (You’ll look into exponents a little later on.)
You use an integer when you’re dealing with what is evidently a whole number: the number of players on a team, for example, or the number of pages in a book. You use a floatingpoint value when the values aren’t integral: the circumference of a circle divided by its diameter, for example, or the exchange rate of the UK£ against the US$.
Floatingpoint numbers are particularly helpful when you’re dealing with very small or very large quantities: the weight of an electron, the diameter of the galaxy, or the velocity of a bat out of hell, perhaps. The term “floatingpoint number” is used because while these values are represented by a fixed number of digits, called the precision, the decimal point “floats” and can be moved in either direction in relation to the fixed set of digits.
Letting the Point Float
Look at these two numbers:
0.000000000000000000001234567 1.234567×1021
123456700000000000000000000.0 1.234567×10+26
Both numbers have seven digits of precision, but they’re very different numbers, the first being an extremely small number and the second being very large. A floatingpoint representation of each number on the left is shown to its right. Multiplying the number by a power of 10 shifts the decimal point in the base number, 1.234567. This flexibility in positioning the decimal point allows a huge range of numbers to be represented and stored, from the very small to the very large, in a modest amount of memory.
You’ll look at how to use integers first, as they’re the simpler of the two. You’ll come back to working with floatingpoint values as soon as you’re done with integers.
Integer LiteralsYou can write integer literals in a very straightforward way. Here are some examples:
123 +123 123 22333
Here, the + and – signs in the first two examples are examples of the unary operators I mentioned earlier. You could omit the + in the second example, as it’s implied by default, but if you think putting it in makes things clearer, that’s not a problem. The literal +123 is the same as 123 . The fourth example is the number that you would normally write as 22,333, but you must not use commas within an integer literal. If you include a comma, the compiler is likely to treat your number as two numbers separated by the comma.
You can’t write just any old integer value that you want, either. To take an extreme example, an integer with 100 digits won’t be accepted. There are upper and lower limits on integer literals, and these are determined by the amount of memory that’s devoted to storing each type of integer value on the computer that you’re using. I come back to this point a little later in the chapter when I discuss integer variables, and I also cover some further options for specifying integer literals.
Of course, although I’ve written the examples of integer literals as decimal values, inside your computer they’re stored as binary numbers. Understanding binary arithmetic is quite important in programming, so in case you’re a little rusty on how binary numbers work, I’ve included a brief overview in Appendix E. If you don’t feel comfortable with binary and hexadecimal numbers, I suggest you take a look at the overview in Appendix E before continuing with the next section.
Hexadecimal Integer Literals
The previous examples of integer literals were decimal integers, but you can also write integers as hexadecimal values. To indicate that you’re writing a hexadecimal value, you prefix the number with 0x or 0X , so if you write 0x999 , you’re writing a hexadecimal number with three hexadecimal digits. Plain old 999 , on the other hand, is a decimal value with decimal digits, so the value will be completely different. Here are some more examples of integer literals written as hexadecimal values:
Hexadecimal values  0x1AF  0x123  0xA  0xCAD  0xFF 

Corresponding decimal expression  1*162  1*162  10*160  12*162  15*161 
+10*161  +2*161  +10*161  +15*160  
+15*160  +3*160  +13*160  
Decimal value  431  291  10  3245  255 
You’ll remember that in Chapter 1 you saw hexadecimal notation being used in escape sequences that defined characters. What you’re looking at here is different— you’re defining integers. You’ll come back to defining character literals later in this chapter.
The major use for hexadecimal literals is when you want to define a particular pattern of bits. Because each hexadecimal digit corresponds to 4 bits in the binary value, it’s easy to express a particular pattern of bits as a hexadecimal literal. You’ll explore this further in the next chapter.
Octal Integer Literals
You can also write integers as octal values—that is, using base 8. You identify a number as octal by writing it with a leading zero. Here are some examples of octal values:
Octal values 0123 077 010101
Corresponding decimal integers 83 63 4161
Of course, octal numbers can only have digit values from 0 to 7. Octal is used very infrequently these days, and it survives in C++ largely for historical reasons from the time when there were computers around with a word length that was a multiple of 3 bits. However, it’s important to be aware of the existence of octal numbers, because if you accidentally write a decimal number with a leading zero, the compiler will try to interpret it as octal.
CAUTION Don’t write decimal integer values with a leading zero. The compiler will interpret such values as octal (base 8), so a value written as 065 will be equivalent to 53 in decimal notation.
As far as your compiler is concerned, it doesn’t matter which number base you choose when you write an integer value—ultimately, it will be stored in your computer as a binary number. The different ways available to you for writing an integer are there just for your convenience. You could write the integer value fifteen as 15 , as 0xF , or as 017 . These will all result in the same internal binary representation of the value, so you will choose one or other of the possible representations to suit the context in which you are using it.
Integer ArithmeticThe basic arithmetic operations that you can carry out on integers are shown in Table 21.
Table 21. Basic Arithmetic Operations
Operator Operation
+ Addition
– Subtraction
* Multiplication
/ Division
% Modulus (the remainder after division)
The operators in Table 21 work largely in the way you would expect, and notice that they are all binary operators. However, the division operation is slightly idiosyncratic, so let’s examine that in a little more detail. Because integer operations always produce an integer result, an expression such as 11/4 doesn’t result in a value of 2.75 . Instead, it produces 2 . Integer division returns the number of times that the denominator divides into the numerator. Any remainder is simply discarded. So far as the C++ standard is concerned, the result of division by zero is undefined, but specific implementations will usually have the behavior defined and, in some cases, will provide a programmatic means of responding to the situation, so check your product documentation.
Figure 21 illustrates the different effects of the division and modulus operators.
Figure 21. Contrasting the division and modulus operators
The modulus operator, % , which is sometimes referred to as the remainder operator, complements the division operator in that it provides a means for you to obtain the remainder after integer division if you need it. The expression 11%4 results in the value 3 , which is the remainder after dividing 11 by 4. When either or both operands of the modulus operator are negative, the sign of the remainder is up to the particular C++ implementation you’re using, so beware of variations between different systems. Because applying the modulus operator inevitably involves a division, the result is undefined when the right operand is zero.
Let’s see the arithmetic operators in action in an example.
{mospagebreak title=Try It Out: Integer Arithmetic in Action}The following is a program to output the results of a miscellaneous collection of expressions involving integers to illustrate how the arithmetic operators work:
// Program 2.1 – Calculating with integer constants
#include <iostream>
using std::cout;
using std::endl;
int main() {
cout << 10 + 20 << endl; // Output is 30
cout << 10 – 5 << endl; // Output is 5
cout << 10 – 20 << endl; // Output is 10
cout << 10 * 20 << endl; // Output is 200
cout << 10/3 << endl; // Output is 3
cout << 10 % 3 << endl; // Output is 1
cout << 10 % 3 << endl; // Output is 1
cout << 10 % 3 << endl; // Output is 1
cout << 10 % 3 << endl; // Output is 1
cout << 10 + 20/10 – 5 << endl; // Output is 7
cout << (10 + 20)/(10 – 5) << endl; // Output is 6
cout << 10 + 20/(10 – 5) << endl; // Output is 14
cout << (10 + 20)/10 – 5 << endl; // Output is 2
cout << 4*5/3%4 + 7/3 << endl; // Output is 4
return 0; // End the program
}
The output from this example on my system is as follows:
30
5
10
200
3
1
1
1
1
7
6
14
2
4
It doesn’t look particularly elegant with that “ragged right” arrangement, does it? This is a consequence of the way that integers are output by default. Very shortly, you’ll come back to find out how you can make it look prettier. First, though, let’s look at the interesting parts of this example.
HOW IT WORKS
Each statement evaluates an arithmetic expression and outputs the result to the screen, followed by a newline character that moves the cursor to the beginning of the next line. All the arithmetic expressions here are constant expressions, because their values can be completely determined by the compiler before the program executes.
The first five statements are straightforward, and the reasons why they produce the results they do should be obvious to you:
cout << 10 + 20 << endl; // Output is 30
cout << 10 – 5 << endl; // Output is 5
cout << 10 – 20 << endl; // Output is 10
cout << 10 * 20 << endl; // Output is 200
cout << 10/3 << endl; // Output is 3
Because integer operations always produce integer results, the expression 10/3 in the last line results in 3 , as 3 divides into 10 a maximum of three times. The remainder, 1, that is left after dividing by 3 is discarded.
The next four lines show the modulus operator in action:
cout << 10 % 3 << endl; // Output is
1
cout << 10 % 3 << endl; // Output is 1
cout << 10 % 3 << endl; // Output is 1
cout << 10 % 3 << endl; // Output is 1
Here you’re producing the remainder after division for all possible combinations for the signs of the operands. The output corresponding to the first line where both operands are positive is the only one guaranteed to be the same when you run it on your system. The results of the other three lines may have a different sign.
The next four statements show the effects of using parentheses:
cout << 10 + 20/10 – 5 << endl; // Output is 7
cout << (10 + 20)/(10 – 5) << endl; // Output is 6
cout << 10 + 20 /(10 – 5) << endl; // Output is 14
cout << (10 + 20)/10 – 5 << endl; // Output is 2
The parentheses override the “natural order” of execution of the operators in the expressions. The expressions within parentheses are always evaluated first, starting with the innermost pair if they’re nested and working through to the outermost.
In an expression involving several different operators, the order in which the operators are executed is determined by giving some operators priority over others. The priority assigned to an operator is called its precedence.With the operators for integer arithmetic that you’ve seen, the operators * , / , and % form a group that takes priority over the operators + and – , which form another group. You would say that each of the operators * , / , and % has a higher precedence than + and – . Operators within a given group— + and – , for example—have equal precedence. The last output statement in the example illustrates how prece dence determines the order in which the operators are executed:
cout << 4*5/3%4 + 7/3 << endl; // Output is 4
The + operator is of lower precedence than any of the others, so the addition will be performed last. This means that values for the two subexpressions, 4*5/3%4 and 7/3 , will be calculated first. The operators in the subexpression 4*5/3%4 are all of equal precedence, so the sequence in which these will be executed is determined by their associativity. The associativity of a group of operators can be either left or right. An operator that is left associative binds first to the operand on the left of the operator, so a sequence of such operators in an expression will be executed from left to right. Let’s illustrate this using the example.
In the expression 4*5/3%4 , each of the operators is left associative, which means that the left operand of each operator is whatever is to its left. Thus, the left operand for the multiplication operation is 4 , the left operand for the division operation is 4*5 , and the left operand for the modulus operation is 4*5/3 . The expression is therefore evaluated as ((4*5)/3)%4 , which, as I said, is left to right.
Although the associativity of the operators in an expression is involved in determining the sequence of execution of operators from the same group, it doesn’t say anything about the operands. For example, in the expression 4*5/3%4+7/3 , it isn’t defined whether the subexpression 4*5/3%4 is evaluated before 7/3 or vice versa. It could be either, depending on what your compiler decides. Your reaction to this might be “Who cares?” because it makes no difference to the result. Here, that’s true, but there are circumstances in which it can make a difference, and you’ll see some of them as you progress through this chapter.
Operator Precedence and AssociativityNearly all operator groups are left associative in C++, so most expressions involving operators of equal precedence are evaluated from left to right. The only right associative operators are the unary operators, which I’ve already touched upon, and assignment operators, which you’ll meet later on.
You can put the precedence and associativity of the integer arithmetic operators into a little table that indicates the order of execution in an arithmetic expression, as shown in Table 22.
Table 22. The Precedence and Associativity of the Arithmetic Operators
Operators Associativity
unary + – Right
* / % Left
+ – Left
Each line in Table 22 is a group of operators of equal precedence. The groups are in sequence, with the highest precedence operators in the top line and the lowest precedence at the bottom. As it only contains three lines, this table is rather simplistic, but you’ll accumulate many more operators and add further lines to this table as you learn more about C++.
NOTE The C++ standard doesn’t define the precedence of the operators directly, but it can be determined from the syntax rules that are defined within the standard. In most instances it’s easier to work out how a given expression will execute from the operator precedence than from the syntax rules, so I’ll consider the precedence of each operator as I introduce it.
If you want to see the precedence table for all the operators in C++, you can find it in Appendix D.
{mospagebreak title=Try It Out: Fixing the Appearance of the Output}Although it may not appear so, the output from the previous example is right justified. The “ragged right” appearance is due to the fact that the output for each integer is in a field width that’s exactly the correct number of characters to accommodate the value. You can make the output look tidier by setting the field width for each data item to a value of your choice, as follows:
Although it may not appear so, the output from the previous example is right justified. The “ragged right” appearance is due to the fact that the output for each integer is in a that’s exactly the correct number of characters to accommodate the value. You can make the output look tidier by setting the field width for each data item to a value of your choice, as follows:// Program 2.1A – Producing neat output
#include
using std::endl;
using std::setw;
int main()
{
cout << setw(10) << 10 + 20 << endl; // Output is 30
cout << setw(10) << 10 – 5 << endl; // Output is 5
cout << setw(10) << 10 – 20 << endl; // Output is 10
cout << setw(10) << 10 * 20 << endl; // Output is 200
cout << setw(10) << 10/3 << endl; // Output is 3
cout << setw(10) << 10 % 3 << endl; // Output is 1
cout << setw(10) << 10 % 3 << endl; // Output is 1
cout << setw(10) << 10 % 3 << endl; // Output is 1
cout << setw(10) << 10 % 3<< endl; // Output is 1
cout << setw(10) << 10 + 20/10 – 5 << endl; // Output is 7
cout << setw(10) << (10 + 20)/(10 – 5) << endl; // Output is 6
cout << setw(10) << 10 + 20/(10 – 5) << endl; // Output is 14
cout << setw(10) << (10 + 20)/10 – 5 << endl; // Output is 2
cout << setw(10) << 4*5/3%4 + 7/3 << endl; // Output is 4
return 0; // End the program
}
Now the output looks like this:
30
5
10
200
3
1
1
1
1
7
6
14
2
4
HOW IT WORKS
That’s much nicer, isn’t it? The tidy formatting is accomplished by the changes to the output statements. Each value to be displayed is preceded in the output by setw(10) , as in the first statement:
cout << setw(10) << 10 + 20 << endl; // Output is 30
setw() is called a manipulator because it enables you to manipulate, or control, the appearance of the output. A manipulator doesn’t output anything; it just modifies the output process. Its effect is to set the field width for the next value to be output to the number of characters that you specify between the parenthe ses, which is 10 in this case. The field width that you set by using setw() only applies to the next value that is written to cout . Subsequent values will be presented in the default manner.
The additional
#include
statement for the standard header <iomanip>
Calculating with integer constants is all very well, but you were undoubtedly expecting a bit more sophistication in your C++ programs than that. To do more, you need to be able to store data items in a program, and this facility is provided by variables. A variable is an area in memory that’s identified by a name that you supply and that you can use to store an item of data of a particular type. Specifying a variable therefore requires two things: you must give it a name, and you must identify what kind of data you propose to store in it. First of all, let’s consider what options you have for defining variable names.
Calculating with integer constants is all very well, but you were undoubtedly expecting a bit more sophistication in your C++ programs than that. To do more, you need to be able to store data items in a program, and this facility is provided by variables. A is an area in memory that’s identified by a name that you supply and that you can use to store an item of data of a particular type. Specifying a variable therefore requires two things: you must give it a name, and you must identify what kind of data you propose to store in it. First of all, let’s consider what options you have for defining variable names. Variable NamesAs you saw in Chapter 1, the name that you give to a variable can consist of any combination of upper or lowercase letters, underscores, and the digits 0 to 9, but it must begin with a letter or an underscore. As I said in Chapter 1, the ANSI standard says that a variable name can also include UCS characters, and although you could use this in defining your variable names, it’s there to allow compilers to accommodate the use of national language characters that aren’t in the basic set of upper and lowercase letters ( A to Z).
Don’t forget, you must not express any character from the basic source character set as a UCS character. All characters from the basic source character set must appear as their explicit character representation.
You saw some examples of valid variable names in Chapter 1, but here are a few more:
value monthlySalary eight_ball FIXED_VALUE JimBob
Just to remind you of what I said in Chapter 1, a variable name can’t begin with a digit, so names such as 8ball and 7Up aren’t valid. Also, because C++ is a casesensitive language, republican and Republican are different names. You shouldn’t use variable names that begin with an underscore followed by a capital letter or that contain two successive underscores, as names of these forms are reserved for use within the standard libraries.
Generally, the names that you invent for your variables should be indicative of the kind of data that they hold. For instance, a name such as shoe_size is going to mean a whole lot more than ss —always assuming you’re dealing with shoe sizes, of course. You’ll find that you often want to use names that combine two or more words to make your program more understandable. One common approach for doing this uses the underscore character to link words in a single, for example:
line_count pay_rise current_debt
A convention that’s frequently adopted in C++ is to reserve names that begin with a capital letter for naming classes, which are userdefined types. You’ll learn how to define your own data types in Chapter 11. With this approach to names, Point , Person , and Program are all immediately recognizable as userdefined types and not variables. Of course, you’re free to assign any names that you want (as long as they aren’t keywords), but if you choose names that are meaningful and name your variables in a consistent manner, it will make your programs more readable and less errorprone. Appendix B contains a list of all the C++ keywords.
Integer VariablesSuppose you want to use a variable to record how many apples you have. You can create a variable with the name apples by means of a declaration statement for the variable, as shown in Figure 22.
by means of a for the variable, as shown in Figure 22. apples by means of a for the variable, as shown in Figure 22. Suppose you want to use a variable to record how many apples you have. You can create a variable with the name apples by means of a for the variable, as shown in Figure 22.
Figure 22. A variable declaration
The statement in Figure 22 is described as a declaration because it declares the name apples . Any statement that introduces a name into your program is a declaration for that name. The statement in the illustration is also called a definition, because it causes memory to be allocated for the variable apples . Later, you’ll meet statements that are declarations but are not definitions. A variable is created by its definition, so you can only refer to it after the definition statement. If you attempt to refer to a variable prior to its definition, you’ll get an error message from the compiler.
When you define a variable, you can also specify an initial value. For example,
int apples = 10; // Definition for the variable apples
defines the variable called apples and sets its initial value as 10 . The definition in the diagram had no initial value specified, so the memory assigned to the variable would contain whatever junk value was left over from previous use of the memory. Having junk values floating around in your program is a bad idea, and this leads to our first golden rule.
GOLDEN RULE Always initialize your variables when you define them. If you don’t know what value a variable should have when you define it, initialize it to zero.
You can use variables as operands of the arithmetic operators you’ve seen in exactly the same way as you’ve used literals. The value of the variable will be the operand value. If you apply the unary minus operator to a variable, the result is a value that has the opposite sign of the value of the variable, but the same magnitude. This doesn’t change the value stored in the variable, though. You’ll see how to do that very soon.
Let’s try out some integer variables in a little program.
{mospagebreak title=Try It Out: Using Integer Variables}Here’s a program that figures out how your apples can be divided equally among a group of children:
// Program 2.2 – Working with integer variables
#include <iostream> // For output to the screen
using std::cout;
using std::endl;
int main() {
int apples = 10; // Definition for the variable apples
int children = 3; // Definition for the variable children
// Calculate fruit per child
cout << endl // Start on a new line
<< “Each child gets ” // Output some text
<< apples/children // Output number of apples per child
<< ” fruit.”; // Output some more text
// Calculate number left over
cout << endl // Start on a new line
<< “We have ” // Output some text
<< apples % children // Output apples left over
<< ” left over.”; // Output some more text
cout << endl;
return 0; // End the program
}
I’ve been very liberal with the comments here, just to make it clear what’s going on in each statement. You wouldn’t normally put such selfevident information in the comments. This program produces the following output:
Each child gets 3 fruit.
We have 1 left over.
HOW IT WORKS
This example is unlikely to overtax your brain cells. The first two statements in main() define the variables apples and children :
int apples = 10; // Definition for the variable apple
s
int children = 3; // Definition for the variable children
The variable apples is initialized to 10, and children is initialized to 3. Had you wanted, you could have defined both variables in a single statement, for example:
int apples = 10, children = 3;
This statement declares both apples and children to be of type int and initializes them as before. A comma is used to separate the variables that you’re declaring, and the whole thing ends with a semicolon. Of course, it isn’t so easy to add explanatory comments here as there’s less space, but you could split the state ment over two lines:
int apples = 10, // Definition for the variable apple
s
children = 3; // Definition for the variable children
A comma still separates the two variables, and now you have space for the comments at the end of each line. You can declare as many variables as you want in a single statement, and you can spread the statement over as many lines as you see fit. However, it’s considered good style to stick to one declaration per statement.
The next statement calculates how many apples each child gets when the apples are divided up and outputs the result:
cout << endl // Start on a new line
<< “Each child gets ” // Output some text
<< apples/children // Output number of apples per child
<< ” fruit.”; // Output some more text
Notice that the four lines here make up a single statement, and that you put comments on each line that are therefore effectively in the middle of the state ment. The arithmetic expression uses the division operator to obtain the number of apples that each child gets. This expression just involves the two variables that you’ve defined, but in general you can mix variables and literals in an expression in any way that you want.
The next statement calculates and outputs the number of apples that are left over:
cout << endl // Start on a new line
<< “We have ” // Output some text
<< apples % children // Output number of apples per child
<< ” left over.”; // Output some more text
Here, you use the modulus operator to calculate the remainder, and the result is output between the text strings in a single output statement. If you wanted, you could have generated all of the output with a single statement. Alternatively, you could equally well have output each string and data value in a separate statement.
In this example, you used the int type for your variables, but there are other kinds of integer variables.
Integer Variable TypesThe type of an integer variable will determine how much memory is allocated for it and, consequently, the range of values that you can store in it. Table 23 describes the four basic types of integer variables.
Table 23. Basic Integer Variable Types
Type Name Typical Memory per Variable
char 1 byte
short int 2 bytes
int 4 bytes
long int 8 bytes
Apart from type char , which is always 1 byte, there are no standard amounts of memory for storing integer variables of the other three types in Table 23. The only thing required by the C++ standard is that each type in the sequence must occupy at least as much memory as its predecessor. I’ve shown the memory for the types on my system, and this is a common arrangement. The type short int is usually written in its abbreviated form, short , and the type long int is usually written simply as long . These abbreviations correspond to the original C type names, so they’re universally accepted by C++ compilers. At first sight, char might seem an odd name for an integer type, but because its primary use is to store an integer code that represents a character, it does make sense.
You’ve already seen how to declare a variable of type int , and you declare variables of type short int and type long int in exactly the same way. For example, you could define and initialize a variable called bean_count , of type short int , with the following statement:
short int bean_count = 5;
As I said, you could also write this as follows:
int bean_count = 5;
Similarly, you can declare a variable of type long int with this statement:
long int earth_diameter = 12756000L; // Diameter in meters
Notice that I appended an L to the initializing value, which indicates that it’s an integer literal of type long int . If you don’t put the L here, it won’t cause a problem. The compiler will automatically arrange for the value to be converted from type int to type long int . However, it’s good programming practice to make the types of your initializing values consistent with the types of your variables.
Signed and Unsigned Integer Types
Variables of type short int , type int , and type long int can store negative and positive values, so they’re implicitly signed integer types. If you want to be explicit about it, you can also write these types as signed short int , signed int , and signed long int , respectively. However, they’re most commonly written without using the signed keyword.
You may see just the keyword signed written by itself as a type, which means signed int . However, you don’t see this very often probably because int is fewer characters to type! Occasionally you’ll see the type unsigned int written simply as unsigned . Both of these abbreviations originate in C. My personal preference is to always specify the underlying type when using the keywords signed or unsigned , as then there’s no question about what is meant.
An unsigned integer variable can only store positive values, and you won’t be surprised to learn that the type names for three such types are unsigned short int , unsigned int , and unsigned long int . These types are useful when you know you’re only going to be dealing with positive values, but they’re more frequently used to store values that are viewed as bit patterns rather than numbers. You’ll see more about this in Chapter 3, when you look at the bitwise operators that you use to manipulate individual bits in a variable.
You need a way of differentiating unsigned integer literals from signed integer literals, if only because 65535 can be stored in 16 bits as an unsigned value, but as a signed value you have to go to 32 bits. Unsigned integer literals are identified by the letter U or u following the digits of the value. This applies to decimal, hexadecimal, and octal integer literals. If you want to specify a literal to be type unsigned long int , you use both the U or u and the L .
Figure 23. Signed and unsigned integers
Figure 23 illustrates the difference between 16bit signed and unsigned integers. As you’ve seen, with signed integers, the leftmost bit indicates the sign of the number. It will be 0 for a positive value and 1 for a negative value. For unsigned integers, all the bits can be treated as data bits. Because an unsigned number is always regarded as positive, there is no sign bit—the leftmost bit is just part of the number.
If you think that the binary value for –32768 looks strange, remember that negative values are normally represented in 2’s complement form. As you’ll see if you look in Appendix E, to convert a positive binary value to a negative binary value (or vice versa) in 2’s complement form, you just flip all the bits and then add 1. Of course, you can’t represent +32768 as a 16bit signed integer, as the available range only runs from –32768 to +32767.
Signed and Unsigned Char Types
Values stored as type char may actually be signed or unsigned, depending on how your compiler chooses to implement the type, so it may be vary between different computers or even between different compilers on the same computer. If you want a single byte to store integer values rather than character codes, you should explicitly declare the variable as either type signed char or type unsigned char .
Note that although type char will be equivalent to either signed char or unsigned char in any given compiler context, all three are considered to be different types. Of course, the words char , short , int , long , signed , and unsigned are all keywords.
Integer RangesThe basic unit of memory in C++ is a byte. As far as C++ is concerned, a byte has sufficient bits to contain any character in the basic character set used by your C++ compiler, but it is otherwise undefined. As long as a byte can accommodate at least 96 characters, then it’s fine according to the C++ standard. This implies that a byte in C++ is at least 7 bits, but it could be more, and 8bit bytes seem to be popular at the moment at least. The intention here is to remove hardware architecture dependencies from the standard. If at some future date there’s a reason to produce machines with 16bit bytes, for instance, then the C++ standard will accommodate that and will still apply. For the time being, though, you should be safe in assuming that a byte is 8 bits.
As I said earlier, the memory allocated for each type of integer variable isn’t stipulated exactly within the ANSI C++ standard. What is said on the topic is the following:
A variable of type char occupies sufficient memory to allow any character from the basic character set to be stored, which is 1 byte.
A value of type int will occupy the number of bytes that’s natural for the hardware environment in which the program is being compiled.
The signed and unsigned versions of a type will occupy the same amount of memory.
A value of type short int will occupy at least as many bytes as type char ; a value of type int will occupy at least as many bytes as type short int ; and a value of type long int will occupy at least as many bytes as type int .
In a sentence, type char is the smallest with 1 byte, type long is the largest, and type int is somewhere between the two but occupies the number of bytes best suited to your computer’s integer arithmetic capability. The reason for this vagueness is that the number of bytes used for type int on any given computer should correspond to that which results in the most efficient integer arithmetic. This will depend on the architecture of the machine. In most machines, it’s 4 bytes, but as the performance and architecture of computer hardware advances, there’s increasing potential for it to be 8 bytes.
The actual number of bytes allocated to each integer type by your compiler will determine the range of values that can be stored. Table 24 shows the ranges for some typical sizes of integer variables.
Table 24. Ranges of Values for Integer Variables
Type Size (Bytes) Range of Values
char 1 –128 to 127
unsigned char 1 0U to 255U
short 2 –32768 to 32767
unsigned short 2 0U to 65535U
int 4 –2147483648 to 2147483647
unsigned int 4 0U to 4294967295U
long 8 –9223372036854775808L to
9223372036854775807L
unsigned long 8 0 to 18446744073709551615UL
The Type of an Integer Literal
I’ve introduced the idea of prefixes being applied to an integer value to affect the number base for the value. I’ve also informally introduced the notion of the suffixes U and L being used to identify integers as being of an unsigned type or of type long . Let’s now pin these options down more precisely and understand how the compiler will determine the type of a given integer literal.
First, Table 25 presents a summary of the options you have for the prefix and suffix to an integer value.
Table 25. Suffixes and Prefixes for Integer Values
Suffix/Prefix Description
No prefix The value is a decimal number.
Prefix of 0x or 0X The value is a hexadecimal number.
Prefix of 0 (a zero) The value is an octal number.
Suffix of u or U The value is of an unsigned type.
Suffix of L or l (lowercase L) The value is of type long.
The last two items in the table can be combined in any sequence or combination of upper and lowercase U and L , so UL , LU , uL , Lu , and so on are all acceptable. Although you can use the suffix l , which is a lowercase L, you should avoid doing so because of the obvious potential for confusion with the digit 1.
Now let’s look at how the various combinations of prefixes and suffixes that you can use with integer literals will be interpreted by the compiler:
 A decimal integer literal with no suffix will be interpreted as being of type
int
if it can be accommodated within the range of values provided by that type. Other wise, it will be interpreted as being of type
long.

An octal or hexadecimal literal with no suffix will be interpreted as the first of the types
int
,
unsigned int
,
long
, and
unsigned long
in which the value can be accommodated.
 A literal with a suffix of
u
or
U
will be interpreted as being of type
unsigned int
if the value can be accommodated within that type. Otherwise, it will be inter preted as type
unsigned long.

A literal with a suffix of
l
or
L
will be interpreted as being of type
long
if the value can be accommodated within that type. Otherwise, it will be interpreted as type
unsigned long.

A literal with a suffix combining both
U
and
L
in upper or lowercase will be interpreted as being of type
unsigned long.
If the value for a literal is outside the range of the possible types, then the behavior is undefined but will usually result in an error message from the compiler.
You’ll undoubtedly have noticed that you have no way of specifying an integer literal to be of type short int or unsigned short int . When you supply an initial value in a declaration for a variable of either of these types, the compiler will automatically convert the value of the literal to the required type, for example:
unsigned short n = 1000;
Here, according to the preceding rules, the literal will be interpreted as being of type int . The compiler will convert the value to type unsigned short and use that as the initial value for the variable. If you used 1000 as the initial value, this couldn’t be converted to type unsigned short because negative numbers are by definition outside the range of this type. This would undoubtedly result in an error message from the compiler.
Remember that the range of values that can be stored for each integer type is dependent on your compiler. Table 24 shows “typical” values, but your compiler may well allocate different amounts of memory for particular types, thus providing for different ranges of values. You also need to be conscious of the possible variations in types when porting an application from one system to another.
So far, I’ve largely ignored character literals and variables of type char . Because these have some unique characteristics, you’ll deal with character literals and variables that store character codes later in this chapter and press on with integer calculations first. In particular, you need to know how to store a result.
{mospagebreak title=The Assignment Operator}You can store the result of a calculation in a variable using the assignment operator, = . Let’s look at an example. Suppose you declare three variables with the statements
= . Let’s look at an example. Suppose you declare three variables with the statements You can store the result of a calculation in a variable using the , =. Let’s look at an example. Suppose you declare three variables with the statements
int total_fruit = 0;
int apples = 10;
int oranges = 6;
You can calculate the total number of fruit with the statement
total_fruit = apples + oranges;
This statement will first calculate the value on the right side of the = , the sum of apples and oranges , and then store the result in the total_fruit variable that appears on the left side of the = .
It goes almost without saying that the expression on the right side of an assignment can be as complicated as you need. If you’ve defined variables called boys and girls that will contain the number of boys and the number of girls who are to share the fruit, you can calculate how many pieces of fruit each child will receive if you divide the total equally between them with the statement
int fruit_per_child = 0
;
fruit_per_child = (apples + oranges) / (boys + girls);
Note that you could equally well have declared the variable fruit_per_child and initialized it with the result of the expression directly:
int fruit_per_child = (apples + oranges) / (boys + girls);
You can initialize a variable with any expression, as long as all the variables involved have already been defined in preceding statements.
Try It Out: Using the Assignment OperatorYou can package some of the code fragments from the previous section into an executable program, just to see them in action:
// Program 2.3 – Using the assignment operator
#include <iostream>
using std::endl;
int main() {
int apples = 10;
int oranges = 6;
int boys = 3;
int girls = 4;
int fruit_per_child = (apples + oranges)/(boys + girls);
scout << endl
<< “Each child gets ”
<< fruit_per_child << ” fruit.”;
cout << endl;
return 0;
}
This produces the following output:
Each child gets 2 fruit.
This is exactly what you would expect from the preceding discussion. Multiple Assignments
You can assign values to several variables in a single statement. For example, the fol lowing code sets the contents of apples and oranges to the same value:
apples = oranges = 10;
The assignment operator is right associative, so this statement executes by first storing the value 10 in oranges and then storing the value in oranges in apples , so it is effectively
apples = (oranges = 10);
This implies that the expression (oranges = 10) has a value—namely, the value stored in oranges , which is 10. This isn’t merely a curiosity. Occasions will arise in which it’s convenient to assign a value to a variable within an expression and then to use that value for some other purpose. You can write statements such as this:
fruit = (oranges = 10) + (apples = 11);
which will store 10 in oranges , 11 in apples , then add the two together and store the result in fruit . It illustrates that an assignment expression has a value. However, although you can write statements like this, I don’t recommend it. As a rule, you should limit the number of operations per statement. Always assume that one day another programmer will want to understand and modify your code. As such, it’s your job to promote clarity and avoid ambiguity.
Modifying the Value of a VariableBecause the assignment operation first evaluates the right side and then stores the result in the variable on the left, you can write statements like this:
apples = apples * 2;
This statement calculates the value of the right side, apples * 2 , using the current value of apples , and then stores the result back in the apples variable. The effect of the statement is therefore to double the value contained in apples .
The need to operate on the existing value of a variable comes up frequently—so much so, in fact, that C++ has a special form of the assignment operator to provide a shorthand way of expressing this.
The op= Assignment Operators
The op= assignment operators are so called because they’re composed of an operator and an equals sign (=). Using one such operator, the previous statement for doubling the value of apples could be written as follows:
apples *= 2;
This is exactly the same operation as the statement in the last section. The apples variable is multiplied by the value of the expression on the right side, and the result is stored back in apples . The right side can be any expression you like. For instance, you could write
apples *= oranges + 2;
This is equivalent to
apples = apples * (oranges + 2);
Here, the value stored in apples is multiplied by the number of oranges plus 2, and the result is stored back in apples . (Though why you would want to multiply apples and oranges together is beyond me!)
The op= form of assignment also works with the addition operator, so to increase the number of oranges by 2, you could write
oranges += 2;
This has the same effect as the same as the statement
oranges = oranges + 2;
You should be able to see a pattern emerging by now. You could write the general form of an assignment statement using the op= operator as lhs op= rhs; Here, lhs is a variable and rhs is an expression. This is equivalent to the statement
lhs = lhs op (rhs) ;
The parentheses around rhs mean that the expression rhs is evaluated first and th e result becomes the right operand for the operation op.
NOTE lhs is an lvalue , which is an entity to which you can assign a value. Lvalues are so called because they can appear on the left side of an assignment. The result of every expression in C++ will be either an lvalue or an rvalue .An rvalue is a result that isn’t an lvalue—that is, it can’t appear on the left of an assignment operation.
You can use a whole range of operators in the op= form of assignment. Table 26 shows the complete set, including some operators you’ll meet in the next chapter.
Table 26. op= Assignment Operators
Operation Operator Operation Operator
Addition + Bitwise AND &
Subtraction – Bitwise OR 
Multiplication • Bitwise exclusive OR ^
Division / Shift left <<
Modulus % Shift right >>
Note that there can be no spaces between the operator and the = . If you include a space, it will be flagged as an error.
{mospagebreak title=Incrementing and Decrementing Integers}You’ve seen how you can modify a variable using the assignment operator and how you can increment one with the += operator. I’m sure you’ve also deduced that you can decrement a variable with = . However, there are two other rather unusual arithmetic operators that can perform the same tasks. They’re called the increment and decrement operators, ++ and — respectively.
+= operator. I’m sure you’ve also deduced that you can decrement a variable with = . However, there are two other rather unusual arithmetic operators that can perform the same tasks. They’re called the and , ++ and — respectively. You’ve seen how you can modify a variable using the assignment operator and how you can increment one with the += operator. I’m sure you’ve also deduced that you can decrement a variable with =. However, there are two other rather unusual arithmetic operators that can perform the same tasks. They’re called the and , ++ and –respectively.These operators are more than just other options, and you’ll find them to be quite an asset once you get further into applying C++ in earnest. The increment and decrement operators are unary operators that can be applied to an integer variable. For example, assuming the variables are of type int , the following three statements all have exactly the same effect:
count = count + 1 ; count += 1; ++count;
The preceding statements each increment the variable count by 1. The last form, using the increment operator, is clearly the most concise. The action of this operator is different from the other operators that you’ve seen, in that it directly modifies the value of its operand. The effect in an expression is to increment the value of the variable and then to use that incremented value in the expression. For example, suppose count has the value 5, and you execute this statement:
total = ++count + 6;
The increment and decrement operators are of higher precedence than all the binary arithmetic operators. Thus, count will be first incremented to the value 6, and then this value will be used in the evaluation of the expression on the right side of the assign ment operation. The variable total will therefore be assigned the value 12.
You use the decrement operator in the same way as the increment operator:
total = –count + 6;
Assuming count is 6 before executing this statement, the decrement operator will reduce it to 5, and this value will be used to calculate the value to be stored in total , which will be 11.
Postfix Increment and Decrement OperationsSo far, you’ve written the operators in front of the variables to which they apply. This is called the prefix form. The operators can also be written after the variables to which they apply; this is the postfix form, and the effect is slightly different. When you use the postfix form of ++ , the variable to which it applies is incremented after its value is used in context. For example, you can rewrite the earlier example as follows:
total = count++ + 6;
With the same initial value of 5 for count , total is assigned the value 11, because the initial value of count is used to evaluate the expression before the increment by 1 is applied. The variable count will then be incremented to 6. The preceding statement is equivalent to the following two statements:
total = count + 6 ; ++count;
In an expression such as a++ + b , or even a+++b , it’s less than obvious what is meant, or indeed what the compiler will do. These two expressions are actually the same, but in the second case you might really have meant a + ++b , which has a differ ent meaning—it evaluates to one more than the other two expressions. It would be clearer to write the preceding statement as follows:
total = 6 + count++;
Alternatively, you can use parentheses:
total = (count++) + 6;
The rules that I’ve discussed in relation to the increment operator also apply to the decrement operator. For example, suppose count has the initial value 5, and you write the statement
total = –count + 6;
This results in total having the value 10 assigned, whereas if you write the statement
total = 6 + count– ;
the value of total is set to 11.
You should avoid using the prefix form of these operators to operate on a variable more than once in an expression. Suppose the variable count has the value 5, and you write
total = ++count * 3 + ++count * 5;
First, it looks rather untidy, but that’s the least of the problems with this. Second, and crucially, the statement modifies the value of a variable more than once and the result is undefined in C++. You could and should get an error message from the compiler with this statement, but in some instances you won’t. This isn’t a desirable feature in a program to say the least, so don’t modify a variable more than once in a statement.
Note also that the effects of statements such as the following are undefined:
k = ++k + 1;
Here you’re incrementing the value of the variable that appears on the right of the assignment operator, so you’re attempting to modify the value of the variable k twice within one expression. Each variable can be modified only once as a result of evaluating a single expression, and the prior value of the variable may only be accessed to determine the value to be stored. Although such expressions are undefined according to the C++ standard, this doesn’t mean that your compiler won’t compile them. It just means that there is no guarantee of consistency in the results.
The increment and decrement operators are usually applied to integers, particularly in the context of loops, as you’ll see in Chapter 5, and you’ll see later in this chapter that they can be applied to floatingpoint values too. In later chapters, you’ll explore how they can also be applied to certain other data types in C++, in some cases with rather specialized (but very useful) effects.
The const KeywordYou’ll often feel the need to use constants of one kind or another in your programs: the number of days in January, perhaps, or p, the ratio of the circumference of a circle to its diameter, or even the number of buns in a baker’s dozen. However, you should avoid using numeric literals explicitly within calculations; it’s much better to use a variable that you’ve initialized to the appropriate value instead. For example, multiplying a value by 3 doesn’t necessarily communicate that you’re converting from yards to feet, but multiplying by a variable with the name feet_per_yard that you’ve initialized to the value 3 makes it absolutely clear what you’re doing. Explicit numeric literals in a program are sometimes referred to as magic numbers, particularly when their purpose and origin is less than obvious.
that you’ve initialized to the value 3 makes it absolutely clear what you’re doing. Explicit numeric literals in a program are sometimes referred to as , particularly when their purpose and origin is less than obvious. feet_per_yard that you’ve initialized to the value 3 makes it absolutely clear what you’re doing. Explicit numeric literals in a program are sometimes referred to as , particularly when their purpose and origin is less than obvious. You’ll often feel the need to use constants of one kind or another in your programs: the number of days in January, perhaps, or p, the ratio of the circumference of a circle to its diameter, or even the number of buns in a baker’s dozen. However, you should avoid using numeric literals explicitly within calculations; it’s much better to use a variable that you’ve initialized to the appropriate value instead. For example, multiplying a value by 3 doesn’t necessarily communicate that you’re converting from yards to feet, but multiplying by a variable with the name feet_per_yard that you’ve initialized to the value 3 makes it absolutely clear what you’re doing. Explicit numeric literals in a program are sometimes referred to as , particularly when their purpose and origin is less than obvious.Another good reason for using a variable instead of a magic number is that you reduce the number of maintenance points in your code. Imagine that your magic number represents something that changes from time to time—an interest rate, for instance—and that it crops up on several occasions in your code. When the rate changes, you could be faced with a sizable task to correct your program. If you’ve defined a variable for the purpose, you only need to change the value once, at the point of initialization.
Of course, if you use a variable to hold a constant of this kind, you really want to nail the value down and protect it from accidental modifications. You can use the keyword const to do this, for example:
const int feet_per_yard = 3; // Conversion factor yards to feet
You can declare any kind of “variable” as const . The compiler will check that you don’t attempt to alter the value of such a variable. For example, if you put something const on the left of an assignment operator, it will be flagged as an error. The obvious consequence of this is that you must always supply an initial value for a variable that you declare as const .
Be aware that declaring a variable as const alters its type. A variable of type const int is quite different from a variable of type int .
Try It Out: Using constYou could implement a little program to convert a length entered as yards, feet, and inches into inches:
// Program 2.4 – Using const
#include <iostream>
using std::cout;
using std::endl;
int main() {
const int inches_per_foot = 12;
const int feet_per_yard = 3;
int yards = 0;
int feet = 0;
int inches = 0;
// Read the length from the keyboar
d
cout << “Enter a length as yards, feet, and inches: “;
cin >> yards >> feet >> inches;
// Output the length in inches
cout << endl
<< “Length in inches is ”
<< inches + inches_per_foot * (feet + feet_per_yard * yards)
<< endl;
return 0;
}
A typical result from this program is the following:
Enter a length as yards, feet, and inches: 2 2 11
Length in inches is 107
HOW IT WORKS
There’s an extra using statement compared to previous examples:
using std::cin;
This introduces the name cin from the std namespace into the program file that refers to the standard input stream—the keyboard.
You have two conversion constants defined by the statements
const int inches_per_foot = 12;
const int feet_per_yard = 3;
Declaring them with the keyword const will prevent direct modification of these variables. You could test this by adding a statement such as
inches_per_foot = 15;
With a statement like this after the declaration of the constant, the program would no longer compile.
You prompt for input and read the values for yards , feet , and inches with these statements:
cout << “Enter a length as yards, feet, and inches: “;
cin >> yards >> feet >> inches;
Notice how the second line specifies several successive input operations from the stream, cin .You do this by using the extraction operator, >> , that I mentioned briefly in the last chapter. It’s analogous to using cout , the stream output opera tion, for multiple values. The appearance of the insertion and extraction operators provides you with a visual cue as to the direction in which data flows.
The first value read from the keyboard will be stored in yards , the second in feet , and the third in inches . The input handling here is very flexible: you can enter all three values on one line, separated by spaces (in fact, by any whitespace characters), or you can enter them on several lines.
You perform the conversion to inches within the output statement itself:
cout << end
l
<< “Length in inches is “
<< inches + inches_per_foot * (feet + feet_per_yard * yards)
<< endl;
As you can see, the fact that your conversion factors were declared as const in no way affects their use in expressions, just as long as you don’t try to modify them.
{mospagebreak title=Numerical Functions for Integers}I explain functions in detail in Chapter 8, but that won’t stop us from making use of a few from the standard library before that. Let’s do a quick reprise of what’s going on when you use functions and cover some of the terminology they introduce. A function is a named, selfcontained block of code that carries out a specific task. Often, this will involve it performing some operation on data that you supply and then returning the result of that operation to your program. In those circumstances in which a function returns a value that is numeric, the function can participate in an arithmetic expression just like an ordinary variable. In general, a call to a function looks like this:
FunctionName(argument1, argument2, … )
Depending on the function in question, you can supply zero, one, or more values for it to work with by placing them in parentheses after its name when you call it from your program. The values you pass to the function in this way are called arguments. Like all values in C++, the arguments you pass to a function, and the value it returns to your program, have types that you must take care to conform with in order to use the function.
You can access some numerical functions that you can apply to integers by adding an
#include
directive for the
The abs() function returns the absolute value of the argument, which can be of type int or type long . The absolute value of a number is just its magnitude, so taking the absolute value of a negative number returns the number with a positive sign, whereas a positive number will be returned unchanged. The value returned by the abs() function will be of the same type as the argument, for example:
int value = 20;
int result = std::abs(value); // Result is 20
The <sctdlib>
The div() function takes two arguments, both of type int . It returns the result of dividing the first argument by the second as well as the remainder from the operation in the form of a structure of type div_t . I go into structures in detail later on, so for the moment you’ll just see how to access the quotient and the remainder from what is returned by the div() function through an example:
int value = 93;
int divisor = 17;
div_t results = std::div(value, divisor); // Call the function
std::cout << “nQuotient is ” << results.quot; // Quotient is 5
std::cout << “n Remainder is ” << results.rem; // Remainder is 8
The first two statements define the variables value and divisor and give them the initial values 93 and 17, respectively. The next statement calls the div() function to divide value by divisor . You store the resulting structure of type div_t that is returned by the function in the variable results , which is also of type div_t . In the first output statement, you access the quotient from results by appending the name quot to results , separated by a period. The period is called the member access operator, and here you’re using it to access the quot member of the results structure. Similarly, in the last statement you use the member access operator to output the value of the remain der, which is available from the rem member of the results structure. Any structure of type div_t will have members with the names quot and rem , and you always access them by using the member access operator.
Note that you could have used literals directly as arguments to the div() function. In this case, the statement calling the function would be
div_t results = std::div(93, 17);
The ldiv() function performs the same operation as the div() function, but on arguments of type long . The result is returned as a structure of type ldiv_t , which has members quot and rem that are of type long .
CAUTION The
Being able to generate random numbers in a program is very useful. You need to be able to build randomness into game programs, for instance; otherwise, they become very boring very quickly. The
The rand() function return a random integer as type int . The function doesn’t require any arguments, so you can just use it like this:
int random_value = std::rand(); // A random integer
You store the integer that’s returned by the rand() function here in the variable random_value , but you could equally well use it in an arithmetic expression, for example:
int even = 2*std::rand();
The value returned by the
rand()
function will be a value that is from 0 to
RAND_MAX
.
RAND_MAX
is a symbol that is defined in
Because RAND_MAX is defined by a preprocessing macro (you’ll learn what a preprocessing macro is in Chapter 10), it isn’t within the std namespace, so you don’t need to qualify the name when you use it. Any symbol that’s defined by a macro won’t be in the std namespace because it isn’t a name that refers to something. By the time the compiler gets to compile the code, such a symbol will no longer be present because it will have already been replaced by something else during the preprocessing phase.
Making the Sequence Start at Random
Using
rand()
as you have so far, the sequence of numbers will always be the same. This is because the function uses a default seed value in the algorithm that generates the random numbers. This is fine for testing, but once you have a working game program, you’ll really want different sequences each time the program runs. You can change the seed value that will be used to generate the numbers by passing a new seed value as an integer argument to the
srand()
function that is defined in
std::srand(13); // Set seed for rand to 13
The argument to the srand() function must be a value of type unsigned int . Although the preceding statement will result in rand() generating a different sequence from the default, you really need a random seed to get a different sequence from rand() each time you execute a program. Fortunately, the clock on your computer provides a readymade source of random seed values.
The
std::srand((unsigned int)std::time(0));
There are a few things that you’ll have to take on trust for the moment. The argument to the time() function here is 0 . There’s another possibility for the argument, but you don’t need it here so you’ll ignore it. The subexpression (unsigned int) serves to convert the value returned by the time() function to type unsigned int , which is the type required for the argument to the srand() method. Without this, the statement wouldn’t compile. Type conversion is something else that you’ll look into later.
Let’s put a working example together that makes use of random number generation.
Try It Out: Generating Random IntegersHere’s the code:
// Program 2.5 Using Random Integer
s #include
#include <cstdlib>
#include <ctime>
using std::endl;
using std::rand;
using std::srand;
using std::time;
int main() {
const int limit1 = 500; // Upper limit for on set of random values
const int limit2 = 31; // Upper limit for another set of values
cout << “First we will use the default sequence from rand().n”;
cout << “Three random integer from 0 to ” << RAND_MAX << “: ”
<< rand() << ” ” << rand() << ” ” << rand()<< endl;
cout << endl << “Now we will use a new seed for rand().n”;
srand((unsigned int)time(0)); // Set a new seed
cout << “Three random integer from 0 to ” << RAND_MAX << “: “
<< rand() << ” ” << rand() << ” ” << rand()<< endl;
return 0;
}
On my system I get the following output:
First we will use the default sequence from rand().
Three random integer from 0 to 32767: 6334 18467 41
Now we will use a new seed for rand().
Three random integer from 0 to 32767: 4610 32532 28452
HOW IT WORKS
This is a straightforward use of the rand() function, first with the default seed to start the sequence:
cout << “A random integer from 0 to ” << RAND_MAX << “: ”
<< rand() << endl;
Each call to rand() returns a value that will be from 0 to RAND_MAX , and you call the function three times to get a sequence of three random integers.
Next, you set the seed value as the current value of the system clock with this statement:
srand((unsigned int)time(0)); // Set a new seed
This statement will generally result in a different seed being set each time you execute the program. You then repeat the statement that you executed previous ly with the default seed set. Thus, each time you run this program, the first set will always produce the same output, whereas with the second set, the output should be different.
{mospagebreak title=FloatingPoint Operations}Numerical values that aren’t integers are stored as floatingpoint numbers. Internally, floatingpoint numbers have three parts: a sign (positive or negative), a mantissa (which is a value greater than or equal to 1 and less than 2 that has a fixed number of digits), and an exponent. Inside your computer, of course, both the mantissa and the exponent are binary values, but for the purposes of explaining how floatingpoint numbers work, I’ll talk about them as decimal values.
Numerical values that aren’t integers are stored as numbers. Internally, floatingpoint numbers have three parts: a sign (positive or negative), a mantissa (which is a value greater than or equal to 1 and less than 2 that has a fixed number of digits), and an exponent. Inside your computer, of course, both the mantissa and the exponent are binary values, but for the purposes of explaining how floatingpoint numbers work, I’ll talk about them as decimal values.The value of a floatingpoint number is the signed value of the mantissa, multiplied by 10 to the power of the exponent, as shown in Table 27.
Table 27. FloatingPoint Number Value
Sign(+/) Mantissa Exponent Value
– 1.2345 3 –1.2345×103 (which is –1234.5)
You can write a floating point literal in three basic forms:
 As a decimal value including a decimal point (for example, 110.0).
 With an exponent (for example, 11E1) in which the decimal part is multiplied by the power of 10 specified after the E (for exponent). You have the option of using either an upper or a lowercase letter E to precede the exponent.
 Using both a decimal point and an exponent (for example, 1.1E2).
All three examples correspond to the same value, 110.0. Note that spaces aren’t allowed within floatingpoint literals, so you must not write 1.1 E2, for example. The latter would be interpreted by the compiler as two separate things: the floatingpoint literal 1.1 and the name E2.
NOTE A floatingpoint literal must contain a decimal point, or an exponent, or both. If you write a numeric literal with neither, then you have an integer.
FloatingPoint Data TypesThere are three floatingpoint data types that you can use, as described in Table 28.
Data Type  Description 
float  Single precision floatingpoint values 
double  Double precision floatingpoint values 
long double  Doubleextended precision floatingpoint values 
The term “precision” here refers to the number of significant digits in the mantissa. The data types are in order of increasing precision, with float providing the lowest number of digits in the mantissa and long double the highest. Note that the precision only determines the number of digits in the mantissa. The range of numbers that can be represented by a particular type is determined by the range of possible exponents.
The precision and range of values aren’t prescribed by the ANSI standard for C++, so what you get with each of these types depends on your compiler. This will usually make the best of the floatingpoint hardware facilities provided by your computer. Generally, type long double will provide a precision that’s greater than or equal to that of type double , which in turn will provide a precision that is greater than or equal to that of type float .
Typically, you’ll find that type float will provide 7 digits precision, type double will provide 15 digits precision, and type long double will provide 19 digits precision, although double and long double turn out to be the same with some compilers. As well as increased precision, you’ll usually get an increased range of values with types double and long double .
Typical ranges of values that you can represent with the floatingpoint types on an Intel processor are shown in Table 29.
Type  Precision (Decimal Digits)  Range (+ or –) 

float  7  1.2×1038 to 3.4×1038 
double  15  2.2×10308 to 1.8×10308 
long double  19  3.3×104932 to 1.2×104932 
The numbers of decimal digits of precision in Table 29 are approximate. Zero can be represented exactly for each of these types, but values between zero and the lower limit in the positive or negative range can’t be represented, so these lower limits for the ranges are the smallest nonzero values that you can have.
Simple floatingpoint literals with just a decimal point are of type double , so let’s look at how to define variables of that type first. You can specify a floatingpoint variable using the keyword double , as in this statement:
double inches_to_mm = 25.4;
This declares the variable inches_to_mm to be of type double and initializes it with the value 25.4. You can also use const when declaring floatingpoint variables, and this is a case in which you could sensibly do so. If you want to fix the value of the variable, the declaration statement might be
const double inches_to_mm = 25.4; // A constant conversion factor
If you don’t need the precision and range of values that variables of type double provide you can opt to use the keyword float to declare your floatingpoint variable, for example:
float pi = 3.14159f;
This statement defines a variable pi with the initial value 3.14159. The f at the end of the literal specifies it to be a float type. Without the f , the literal would have been of type double , which wouldn’t cause a problem in this case, although you may get a warning message from your compiler. You can also use an uppercase letter F to indicate that a floatingpoint literal is of type float .
To specify a literal of type long double , you append an upper or lowercase L to the number. You could therefore declare and initialize a variable of this type with the statement
long double root2 = 1.4142135623730950488L; // Square root of 2
FloatingPoint OperationsThe modulus operator, % , can’t be used with floatingpoint operands, but all the other binary arithmetic operators that you have seen, + , – , * , and / , can be. You can also apply the prefix and postfix increment and decrement operators, ++ and — , to a floatingpoint variable with the same effect as for an integer—the variable will be incremented or decremented by 1.
As with integer operands, the result of division by zero is undefined so far as the standard is concerned, but specific C++ implementations generally have their own way of dealing with this, so consult your product documentation.
With most computers today, the hardware floatingpoint operations are implemented according to the IEEE 754 standard (also known as IEC 559). Although IEEE 754 isn’t required by the C++ standard, it does provide for identification of some aspects of floatingpoint operations on machines on which IEEE 754 applies. The floatingpoint standard defines special values having a binary mantissa of all zeros and an exponent of all ones to represent +infinity or infinity , depending on the sign. When you divide a positive nonzero value by zero, the result will be +infinity , and dividing a negative value by zero will result in infinity . Another special floatingpoint value defined by IEEE 754 is called Not a Number, usually abbreviated to NaN . This is used to represent a result that isn’t mathematically defined, such as arises when you divide zero by zero or you divide infinity by infinity.
Any subsequent operation in which either or both operands are a value of NaN results in NaN . Once an operation in your program results in a value of ±infinity , this will pollute all subsequent operations in which it participates. Combining a normal value with ±infinity results in ±infinity . Dividing ±infinity by ±infinity or multiplying ±infinity by zero results in NaN . Table 210 summarizes all these possibilities.
Operation  Result  Operation  Result 

±N/0  ±Infinity  0/0  NaN 
±Infinity±N  ±Infinity  ±Infinity/±Infinity  NaN 
±Infinity*N  ±Infinity  InfinityInfinity  NaN 
±Infinity/N  ±Infinity  Infinity*0  NaN 
Using floatingpoint variables is really quite straightforward, but there’s no substitute for experience, so let’s try an example.
{mospagebreak title=Try It Out: FloatingPoint Arithmetic}Suppose that you want to construct a circular pond in which you want to keep a number of fish. Having looked into the matter, you know that you must allow 2 square feet of surface area on the pond for every 6 inches of fish length. You need to figure out the diameter of the pond that will keep the fish happy. Here’s how you can do it:
// Program 2.6 Sizing a pond for happy fis
h #include
int main() { const double fish_factor = 2.0/0.5; // Area per unit length of fish const double inches_per_foot = 12.0; const double pi = 3.14159265;
double fish_count = 0.0; // Number of fish double fish_length = 0.0; // Average length of fish
cout << “Enter the number of fish you want to keep: “; cin >> fish_count; cout << “Enter the average fish length in inches: “; cin >> fish_length; fish_length = fish_length/inches_per_foot; // Convert to feet
// Calculate the required surface area double pond_area = fish_count * fish_length * fish_factor;
// Calculate the pond diameter from the area double pond_diameter = 2.0 * sqrt(pond_area/pi);
cout << “nPond diameter required for ” << fish_count << ” fish is ” << pond_diameter << ” feet.n”; return 0; }
(Continued)
With input values of 20 fish with an average length of 9 inches, this example produces the following output:
Enter the number of fish you want to keep: 20 Enter the average fish length in inches: 9 Pond diameter required for 20 fish is 8.74039 feet.
You first declare three const variables that you’ll use in the calculation:
const double fish_factor = 2.0/0.5; // Area per unit length of fish const double inches_per_foot = 12.0; const double pi = 3.14159265;
Notice the use of a constant expression to specify the value for fish_factor . You can use any expression that produces a result of the appropriate type to define an initializing value for a variable. You have declared fish_factor , inches_per_foot , and pi as const because you don’t want to allow them to be altered.
Next, you declare variables in which you’ll store the user input:
double fish_count = 0.0; // Number of fish double fish_length = 0.0; // Average length of fish
You don’t have to initialize these, but it’s good practice to do so.
Because the input for the fish length is in inches, you need to convert it to feet before you use it in the calculation for the pond:
fish_length = fish_length/inches_per_foot; // Convert to feet
This stores the converted value back in the original variable.
You get the required area for the pond with the following statement:
double pond_area = fish_count * fish_length * fish_factor;
The product of fish_count and fish_length gives the total length of all the fish, and multiplying this by fish_factor gives the required area.
The area of any circle is given by the formula p r2, where r is the radius. You can therefore calculate the radius of the pond as the square root of the area divided by p. The diameter is then twice the radius, and the whole calculation is carried out by this statement:
pond_diameter = 2.0 * sqrt(pond_area / pi);
74 You obtain the square root using a function that’s declared in the standard header
The last step before exiting main() is to output the result:
cout << “nPond diameter required for ” << fish_count << ” fish is ” << pond_diameter << ” feet.n”;
This outputs the pond diameter required for the number of fish specified. Working with FloatingPoint Values
For most computations using floatingpoint values, you’ll find that type double is more than adequate. However, you need to be aware of the limitations and pitfalls of work ing with floatingpoint variables. If you’re not careful, your results may be inaccurate, or even incorrect. The following are common sources of errors when using floatingpoint values:
 Many decimal values don’t convert exactly to binary floatingpoint values. The small errors that occur can easily be amplified in your calculations to produce large errors.
 Taking the difference between two nearly identical values can lose precision. If you take the difference between two values of type
float
that differ in the sixth significant digit, you’ll produce a result that may have only one or two digits of accuracy. The other significant digits that are stored may represent errors.
 Dealing with a wide range of possible values can lead to errors. You can create an elementary illustration of this by adding two values stored as type
float
with 7 digits of precision but in which one value is 108 times larger that the other. You can add the smaller value to the larger as many times as you like, and the larger value will be unchanged. The
header defines constants for the floatingpoint types that are the smallest values that you can add to 1.0 and get a different result. The constants are FLT_EPSILON , DBL_EPSILON , and LDBL_EPSILON .
Let’s see how these errors can manifest themselves in practice, albeit in a somewhat artificial situation.
Try It Out: Errors in FloatingPoint CalculationsHere’s an example contrived to illustrate how the first two points can combine to produce errors:
// Program 2.7 Floating point errors
#include
 

using std::cout;  
using std::endl;  
int main() {  
float value1 = 0.1f;  
float value2 = 2.1f;  
value1 = 0.09f;  // Should be 0.01 
value2 = 2.09f;  // Should be 0.01 
cout << value1 – value2 << endl;  // Should output zero 
return 0;  
} 
The value displayed should be zero, but on my computer this program produces the following:
7.45058e009
The reason for the error is that none of the numerical values is stored exactly. If you add code to output the values of value1 and value2 after they’ve been modified, you should see a discrepancy between them.
Of course, the final difference between the values of value1 and value2 is a very small number, but you could be using this totally spurious value in other calculations in which the error could be amplified. If you multiply this result by 1010, say, you’ll get an answer around 7.45, when the result should really be zero. Similarly, if you compare these two values, expecting them to be equal, you don’t get the result you expect.
CAUTION Never rely on an exact floatingpoint representation of a decimal value in your program code.
Tweaking the Output
The previous program outputs the floatingpoint value in a very sensible fashion. It gave you 5 decimal places, and it used scientific notation (that is, a mantissa and an exponent). However, you could have chosen to have the output displayed using “normal” decimal notation by employing some more output manipulators.
{mospagebreak title=Try It Out: Yet More Output Manipulators}Here’s the same code as in the previous “Try It Out” exercise, except that it uses additional manipulators to improve the appearance of the output:
// Program 2.8 Experimenting with floating point output#include
using std::cout; using std::endl;
int main() { float value1 = 0.1f; float value2 = 2.1f; value1 = 0.09f; value2 = 2.09f;
cout << setprecision(14) << fixed;cout << value1 – value2 << endl;
cout << setprecision(5) << scientific; cout << value1 – value2 << endl;
return 0; } // Should be 0.01
// Should be 0.01
// Change to fixed notation
// Should output zero
// Set scientific notation // Should output zero
When I run the modified program, this is the output I get:
0.00000000745058 7.45058e009(Continued)
This code uses three new manipulators. The setprecision() manipulator specifies how many decimal places should appear after the decimal point when you’re outputting a floatingpoint number. The fixed and scientific manipulators complement one another and choose the format in which a floatingpoint number should be displayed when they’re written to the stream.
By default, your C++ compiler will select either scientific or fixed , depending on the particular value you’re outputting, and you saw in the first version of this program that it performed that task admirably. The default number of decimal places isn’t defined in the standard, but five is common.
Let’s look at the changes made. Apart from the
#include
for
cout << setprecision(14) << fixed;  // Change to fixed notation 
cout << value1 – value2 << endl;  // Should output zero 
cout << setprecision(5) << scientific;  // Set scientific notation 
cout << value1 – value2 << endl;  // Should output zero 
The first line is easy: you use the manipulators like you used setw() , by sending them to the output stream with the insertion operator. Their effects can then clearly be seen in the first line of output: you get a floatingpoint value with 14 decimal places and no exponent.
Note that these manipulators differ from setw() in that they’re modal.In other words, they remain in effect for the stream until the end of the program, unless you set a different option. That’s the reason for the third line in the preceding code—you have to set scientific mode and a precision of 5 explicitly in order to return to “default” behavior. You can see that you’ve succeeded, though, because the second line of output is the same as the one produced by the original program.
NOTE Actually, the
The
Table 211.
abs(arg)
fabs(arg) ceil(arg)
floor(arg)
exp(arg) log(arg) log10(arg) pow(arg1, arg2)
DescriptionReturns the absolute value of arg as the same type as
arg
, where
ar
g
can be of any floatingpoint type. There are versions of the
abs()
function declared in the
Returns the absolute value of arg as the same type as the argument.
The argument can be int , long , float , double , or long double. Returns a floatingpoint value of the same type as arg that is the smallest integer greater than or equal to arg , so ceil(2.5) produces the value 3.0. arg can be of any floatingpoint type.
Returns a floatingpoint value of the same type as arg that is the largest integer less than or equal to arg so the value returned by floor(2.5 ) will be 2.0. arg can be of any floatingpoint type .
Returns the value of e arg as the same type as arg . arg can be of any
floatingpoint type. The log function returns the natural logarithm (to base e) of arg as the same type as arg . arg can be any floatingpoint type.
The log10 function returns the logarithm to base 10 of arg as the same
type as arg . arg can be any floatingpoint type. The pow function returns the value of arg1 raised to the power arg1, which is arg1arg2. Thus the result of pow(2, 3) will be 8, and the result of pow(1.5, 3) will be 3.375. The arguments can be both of type int or any floatingpoint type. The second argument, arg2 , may also be of type int with arg1 of type int , or long , or any floatingpoint type. The value returned will be of the same type as arg1.
Table 212 shows the trigonometric functions that you have available in the
Function  Description 
cos(angle)  Returns the cosine of the angle expressed in radians that is passed as the argument. 
sin(angle)  Returns the sine of the angle expressed in radians that is passed as the 
argument.  
tan(angle)  Returns the tangent of the angle expressed in radians that is passed as the argument. 
cosh(angle)  Returns the hyperbolic cosine of the angle expressed in radians that is passed as the argument. The hyperbolic cosine of a variable x is given by formula (exex)/2. 
sinh(angle)  Returns the hyperbolic sine of the angle expressed in radians that is passed as the argument. The hyperbolic sine of a variable x is given by the formula (ex+ex)/2. 
tanh(angle)  Returns the hyperbolic tangent of the angle expressed in radians that is passed as the argument. The hyberbolic tangent of a variable x is given by the hyperbolic sine of x divided by the hyperbolic cosine of x. 
acos(arg)  Returns the inverse cosine (arccosine) of arg . The argument must be between –1 and +1. The result is in radians and will be from 0 to p. 
asin(arg)  Returns the inverse sine (arcsine) of the argument. The argument must be between –1 and +1. The result is in radians and will be from –p/2 to +p/2. 
atan(arg)  Returns the inverse tangent (arctangent) of the argument. The result is in radians and will be from –p/2 to +p/2. 
atan2(arg1, arg2)  This function requires two arguments of the same floatingpoint type. The function returns the inverse tangent of arg1/arg2 . The result will be in the range from –p to +p radians and of the same type as the 
arguments. 
The arguments to these functions can be of any floatingpoint type and the result will be returned as the same type as the argument(s).
Let’s look at some examples of how these are used. Here’s how you can calculate the sine of an angle in radians:
double angle = 1.5; // In radians double sine_value = std::sin(angle);
If the angle is in degrees, you can calculate the tangent by using a value for p to convert to radians:
float angle_deg = 60.0f; // Angle in degree s const float pi = 1.14159f; const float pi_degrees = 180.0f; float tangent = std::tan(pi*angle_deg/pi_degrees);
If you know the height of the church steeple is 100 feet and you’re standing 50 feet from the base of the steeple, you can calculate the angle in radians of the top of the
steeple like this:  

double height = 100.0;  // Steeple height feet 
double distance = 50.0;  // Distance from base 
angle = std::atan2(height, distance);  // Result in radians 
You can use this value in angle and the value of distance to calculate the distance from your toe to the top of the steeple:
double toe_to_tip = distance*std::cos(angle);
Of course, fans of Pythagoras of Samos could obtain the result much more easily, like this:
double toe_to_tip = std::sqrt(std::pow(distance,2) + std::pow(height, 2);
{mospagebreak title=Working with Characters}Variables of type char are primarily used to store a code for a single character and occupy 1 byte in memory. The C++ standard doesn’t specify the character encoding to be used for representing the basic character set, so this is determined by a particular compiler. It’s typically, but not exclusively, ASCII.
char are primarily used to store a code for a single character and occupy 1 byte in memory. The C++ standard doesn’t specify the character encoding to be used for representing the basic character set, so this is determined by a particular compiler. It’s typically, but not exclusively, ASCII. Variables of type char are primarily used to store a code for a single character and occupy 1 byte in memory. The C++ standard doesn’t specify the character encoding to be used for representing the basic character set, so this is determined by a particular compiler. It’s typically, but not exclusively, ASCII.You declare variables of type char in the same way as variables of the other types that you’ve seen, for example:
char letter; char yes, no;
The first statement declares a single variable of type char with the name letter . The second variable declares two variables of type char having the names yes and no . Each of these variables can store the code for a single character. Because you haven’t pro vided initial values for these variables, they’ll contain junk values.
Character LiteralsWhen you declare a variable of type char , you can initialize it with a character literal. You write a character literal as the character that you require between single quotes. For example, ‘z’ , ‘3’ , and ‘?’ are all character literals.
Some characters are problematical to enter as literals. Obviously, a single quote presents a bit of a difficulty because it’s a delimiter for a character literal. In fact, it isn’t legal in C++ to put either a single quote or a backslash character between single quotes. Control characters such as newline and tab are also a problem because they result in an effect when you press the key for the appropriate character rather than entering the character as data. You can specify all of these problem characters by using escape sequences that begin with a backslash, as shown in Table 213.
To specify a character literal corresponding to any of these characters, you just type in the corresponding escape sequence between single quotes. For instance, newline is ‘n’ and backslash is ” .
There are also escape sequences that you can use to specify a character by its code expressed as either an octal or a hexadecimal value. The escape sequence for an octal character code is one to three octal digits preceded by a backslash. The escape sequence for a hexadecimal character code is one or more hexadecimal digits preceded by x . You write both forms between single quotes when you want to define a character literal. For example, the letter ‘A’ could be written as hexadecimal ‘x41’ or octal ’81’ in USASCII code. Obviously, you could write codes that won’t fit within a single byte, in which case the result is implementation defined.
If you write a character literal with more than one character between the single quotes and the characters don’t represent an escape sequence— ‘abc’ is an example— then the literal is described as a multicharacter literal and will be of type int . The numerical value of such a literal is implementation defined but will usually be the result of placing the 1byte codes for the characters in successive bytes of the int value. If you specify a multicharacter literal with more than four characters, this will usually result in an error message from the compiler.
You now know enough about character literals to initialize your variables of type char properly.
Initializing char Variables
You can define and initialize a variable of type char with the statement
char letter = ‘A’; // Stores a single letter ‘A’
82 This statement defines the variable with the name letter to be of type char with an initial value ‘A’ . If your compiler represents characters using USASCII codes, this will have the decimal value 65.
You can declare and initialize multiple variables in a single statement:
char yes = ‘y’, no = ‘n’, tab = ‘t’;
Because you can treat variables of type char as integers, you could equally well declare and initialize the variable letter with this statement:
char letter = 65; // Stores the ASCII code for ‘A’
Remember that type char may be signed or unsigned by default, depending on the compiler, so this will affect what numerical values can be accommodated. If char is unsigned, values can be from 0 to 255. If it’s signed, values can be from –128 to +127. Of course, the range of bit patterns that can be stored is the same in both cases. They’re just interpreted differently.
Of course, you can use the variable letter as an operand in integer operations, so you can write
letter += 2;
This will result in the value stored in letter being incremented to 67, which is ‘C’ in USASCII. You can find all the USASCII codes in Appendix A of this book.
CAUTION Although I’ve assumed USASCII coding in the examples, as I noted earlier although this is usually the case this doesn’t have to be so. On older main frame computers, for instance, characters may be represented using Extended Binary Coded Decimal Interchange Code (EBCDIC), in which the codes for some characters are different from USASCII.
You can explicitly declare a variable as type signed char or unsigned char , which will affect the range of integers that can be represented. For example, you can declare a variable as follows:
unsigned char ch = 0U;
In this case, the numerical values can range from 0 to 255.
When you read from a stream into a variable of type char , the first nonwhitespace character will be stored. This means that you can’t read whitespace characters in this way—they’re simply ignored. Further, you can’t read a numerical value into a variable of type char —if you try, you’ll find that the character code for the first digit will be stored. When you output a variable of type char to the screen, it will be as a character, not a numerical value. You can see this demonstrated in the next example.
Try It Out: Handling Character ValuesThis example reads a character from the keyboard, outputs the character and its numerical code, increments the value of the character, and outputs the result as a character and as an integer:
// Program 2.9 – Handling character value
s #include
int main() { char ch = 0; int ch_value = 0;
// Read a character from the keyboard cout << “Enter a character: “; cin >> ch; ch_value = ch; // Get integer value of character
cout << endl << ch << ” is ” << ch_value;
ch_value = ++ch; // Increment ch and store as integer
cout << endl << ch << ” is ” << ch_value << endl;
return 0; }
Typical output from this example is as follows:
Enter a character: w
w is 119 x is 120
After prompting for input, the program reads a character from the keyboard with the statement
cin >> ch;
Only nonwhitespace characters are accepted, so you can press Enter or enter spaces and tabs and they’ll all be ignored.
Stream output will always output the variable ch as a character. To get the numer ical code, you need a way to convert it to an integer type. The next statement does this:
ch_value = ch; // Get integer value of character
The compiler will arrange to convert the value stored in ch from type char to type int so that it can be stored in the variable ch_value . You’ll see more about automatic conversions in the next chapter, when I discuss expressions involving values of different types.
Now you can output the character as well as its integer code with the following statement:
cout << end l << ch << ” is ” << ch_value;
The next statement demonstrates that you can operate with variables of type char as integers:
ch_value = ++ch; // Increment ch and store as integer
This statement increments the contents of ch and stores the result in the variable ch_value , so you have both the next character and its numerical representation. This is output to the display with exactly the same statement as was used previ ously. Although you just incremented ch here, variables of type char can be used with all of the arithmetic operators, just like any of the integer types.
Working with Extended Character SetsSinglebyte character codes such as ASCII or EBCDIC are generally adequate for national language character sets that use Latin characters. There are also 8bit character encodings that will accommodate other languages such as Greek or Russian. However, if you want to work with these and Latin characters simultaneously, or if you want to handle character sets for Asian languages that require much larger numbers of character codes than the ASCII set, 256 character codes doesn’t go far enough.
The type wchar_t is a character type that can store all members of the largest extended character set that’s support by an implementation. The type name derives from wide characters, because the character is “wider” than the usual singlebyte character. By contrast, type char is referred to as “narrow” because of the limited range of character codes that are available. The size of variables of type wchar_t isn’t stipulated by the C++ standard, except that it will have the same characteristics as one of the other integer types. It is often 2 bytes on PCs, and typically the underlying type is unsigned short , but it can also be 4 bytes with some compilers, especially those implemented on Unix workstations.
WideCharacter Literals
You define widecharacter literals in the same way as narrow character literals that you use with type char , but you prefix them with the letter L. For example,
wchar_t wide_letter = L’Z’;
defines the variable wide_letter to be of type wchar_t and initializes it to the widecharacter representation for Z.
Your keyboard may not have keys for representing other national language characters, but you can still create them using hexadecimal notation, for example:
wchar_t wide_letter = L’x0438′; // Cyrillic
The value between the single quotes is an escape sequence that allows you to specify a character by a hexadecimal representation of the character code. The backslash indicates the start of the escape sequence, and the x after the backslash signifies that the code is hexadecimal. The absence of x or X would indicate that the characters that follow are to be interpreted as octal digits.
Of course, you could also use the notation for UCS character literals:
wchar_t wide_letter = L’u0438′; // Cyrillic
If your compiler supports 4byte UCS characters, you could also initialize a variable of type wchar_t with a UCS character specified as Udddddddd , where d is a hexadecimal digit.
WideCharacter Streams
The streams
cin
and
cout
that you’ve been using are narrowcharacter streams. They only handle characters that consist of a single byte, so you can’t extract from
cin
into a variable of type
wchar_t
. The
wchat_t wide_letter = 0 ; std::wcin >> wide_letter; // Read a wide character
Although you’ll always be able to write wide characters to wcout , this doesn’t mean that such characters will display correctly or at all. It depends on if your operating sys tem recognizes the character codes.
{mospagebreak title=Functional Notation for Initial Values}An alternative notation for specifying the initial value for a variable when you declare it is called functional notation. The term stems from the fact that you put the initial value between parentheses after the variable name, so it looks like a function call, as you’ll discover later on.
An alternative notation for specifying the initial value for a variable when you declare it is called . The term stems from the fact that you put the initial value between parentheses after the variable name, so it looks like a function call, as you’ll discover later on.Let’s look at an example. Instead of writing a declaration as
int unlucky = 13;
you have the option to write the statement as
int unlucky(13);
Both statements achieve exactly the same result: they declare the variable unlucky as type int and give it an initial value of 13.
You can initialize other types of variables using functional notation. For instance, you could declare and initialize a variable to store a character with this statement:
char letter(‘A’);
However, functional notation for initializing variables is primarily used for the initialization of variables of a data type that you’ve defined. In this case, it really does involve calling a function. The initialization of variables of the fundamental types in C++ normally uses the approach you have taken up to now. You’ll have to wait until Chapter 11 to find out about creating your own types and how those kinds of variables get initialized!
SummaryIn this chapter, I covered the basics of computation in C++. You learned about most of the fundamental types of data that are provided for in the language. The essentials of what I’ve discussed up to now are as follows:
 Numeric and character constants are called literals.
 You can define integer literals as decimal, hexadecimal, or octal values.
 A floatingpoint literal must contain a decimal point, or an exponent, or both.
 Named objects in C++, such as variables, can have names that consist of a sequence of letters and digits, the first of which is a letter, and where an underscore is considered to be a letter. Upper and lowercase letters are distinguished.
 Names that begin with an underscore followed by a capital letter, and names that contain two successive underscores, are reserved for use within the standard library, so you shouldn’t use them for names of your own variables.
 All literals and variables in C++ are of a given type.
 The basic types that can store integers are
short
,
int
, and
long
. These store signed integers by default, but you can also use the type modifier
unsigned
preceding any of these type names to produce a type that occupies the same number of bytes but only stores unsigned integers.
 A variable of type
char
can store a single character and occupies 1 byte. The type
char
may be
signed
or
unsigned
by default, depending on your compiler. You can also use variables of the types
signed char
and
unsigned char
to store integers.
 The type
wchar_t
can store a wide character and occupies either 2 or 4 bytes, depending on your compiler.
 The floatingpoint data types are
float
,
double
, and
long double
.
 The name and type of a variable appear in a declaration statement ending with a semicolon. A declaration for a variable that results in memory being allocated is also a definition of the variable.
 Variables may be given initial values when they’re declared, and it’s good programming practice to do so.
 You can protect the value of a “variable” of a basic type by using the modifier
const
. The compiler will check for any attempts within the program source file to modify a variable declared as
const
.
 An lvalue is an object or expression that can appear on the left side of an assignment. Non
const
variables are examples of lvalues.
Although I discussed quite a few basic types in this chapter, don’t be misled into thinking that’s all there are. There are some other basic types, as well as more complex types based on the basic set, as you’ll see, and eventually you’ll be creating original types of your own.
{mospagebreak title=Exercises}The following exercises enable you to try out what you’ve learned in this chapter. If you get stuck, look back over the chapter for help. If you’re still stuck, you can download the solutions from the Downloads area of the Apress website ( http://www.apress.com ), but that really should be a last resort.
http://www.apress.com ), but that really should be a last resort. The following exercises enable you to try out what you’ve learned in this chapter. If you get stuck, look back over the chapter for help. If you’re still stuck, you can download the solutions from the Downloads area of the Apress website (http://www.apress.com), but that really should be a last resort.Exercise 21. Write a program that will compute the area of a circle. The program should prompt for the radius of the circle to be entered from the keyboard, calculate the area using the formula area = pi * radius * radius , and then display the result.
Exercise 22. Using your solution for Exercise 21, improve the code so that the user can control the precision of the output by entering the number of digits required. (Hint: Use the setprecision() manipulator.)
Exercise 23. Create a program that converts inches to feetandinches— for example, an input of 77 inches should produce an output of 6 feet and 5 inches. Prompt the user to enter an integer value corresponding to the number of inches, and then make the conversion and output the result. (Hint: Use a const to store the inchestofeet conversion rate; the modulus operator will be very helpful.)
Exercise 24. For your birthday you’ve been given a long tape measure and an instrument that allows you to determine angles—the angle between the horizontal and a line to the top of a tree, for instance. If you know the distance, d, you are from a tree, and the height, h, of your eye when peering into your anglemeasuring device, you can calculate the height of the tree with this formula:
h+d*tan(angle)
Create a program to read h in inches, d in feet and inches, and angle in degrees from the keyboard, and output the height of the tree in feet.
NOTE There is no need to chop down any trees to verify the accuracy of your program. Just check the solutions on the Apress website ( http://www.apress.com/book/download.html ).
Exercise 25. Here’s an exercise for puzzle fans. Write a program that will prompt the user to enter two different positive integers. Identify in the output the value of the larger integer and the value of the smaller integer. (This can be done with what you’ve learned in this chapter!)