Previous Table of Contents Next


7.2.2.4. Characters

In C++, characters are just tiny integers. In particular, they participate in arithmetic the same way as integers. Why bother, then, with a separate character type?

One reason is that characters are not required to contain more than 8 bits, which means that if characters were some kind of int, it would be necessary to find a separate name for the character type anyway. Another is notational convenience: By making characters a distinct type, it is possible to treat them differently from integers in overloading contexts, so that

   cout << ‘a’ << endl;

prints the character a and not the corresponding integer value.

As is the case with integers, characters can be signed or not, so there are distinct signed char and unsigned char types. In addition, there is a plain char type, which is required to have the same representation as one of the other two types, but it is up to the implementation which of those types it should be. As usual, the choice is intended to reflect which representation is most natural for the machine.

There is also a “wide character” type called wchar_t, which must contain at least 16 bits, and which is intended to be used for representing characters in languages such as Japanese, which have many more characters than the Latin alphabet provides.

Character literals, such as ‘a’, are enclosed in single quotes. Certain nonprinting characters have special representations, such as ‘\n’ for a newline character, ‘\t’ for a tab, and ‘\b’ for a backspace. This use of the \ character implies that one must write ‘\\’ to represent a single \, and ‘\’’ to represent a .

It is also possible to write a character literal that represents the character corresponding to a particular integer, either in octal or hexadecimal. So, for instance, ‘\40’ is the character equivalent to 32 (octal 40), and is the same character as ‘\x20’. On implementations based on the ASCII character set, that character is the same as ‘ ‘. The most common use of this notation is ‘\0’, or the null character, which, as we shall see, has a special conventional role in C++ programs.

7.2.2.5. Floating-Point Arithmetic

C++ has three floating-point types, called float, double, and long double in order of nondecreasing precision. The term “nondecreasing” is appropriate instead of “increasing” because the implementation can implement float with the same precision as double or double with the same precision as long double.

The double type is preferred, in the sense that ordinary floating-point literals such as 3.5 have type double. Literals in the other two types look like 3.5F (or 3.5f) and 3.5LF (or 3.5lf).

All the arithmetic operators that work with integers work with floating-point numbers as well, except for the shift operators. There is no exponentiation operator, but there is a library function called pow that has the equivalent effect.

7.2.3. Enumerated Types

It is often useful to be able to define a variable that can take on one of a set of values that are known during compilation. For example, we might want to record the state of a traffic light (or a collection of traffic lights). In C++, we call such types enumerated types:

   enum TrafficLight { broken, red, yellow, green };

This declaration defines a type called TrafficLight. Variables of that type can have one of four values, called enumerators, namely broken, red, yellow, or green. We can then write, for example:

   TrafficLight tl;
   
   tl = yellow;
   if (tl == green) {
       // something is wrong
   }

Enumerated types are distinct from other numeric types, but they can be converted to integers. So, for example, if our traffic light is still yellow, executing

   cout << tl << endl;

will print 2. It will not print yellow, because C++ does not want to impose the overhead of storing the names of all enumerated types on programs that do not need those names.

As this example implies, the values of enumerated types correspond to consecutive integers, starting from zero. If a value of an enumerated type is used in a context that requires an integer, the value will be converted automatically.

It is also possible to state explicit values for the enumerators:

   enum Operator { plus = ‘+’, minus = ‘-’, times = ‘*’, divide = ‘/’ };

The character literals are taken as the integers that correspond to those characters in the machine’s character set. As this example implies, such usage provides a convenient way to ascribe names to characters when writing lexical analyzers and similar programs.

7.2.4. Numeric Conversions

Many rules govern the value of expressions that contain operands of several numeric types. Usually, the precise details of the rules are not important. Approximately, conversions happen as needed to bring the operands of each operator to a common type, and when there is a choice, conversions that preserve information are preferred over conversions that lose information. Moreover, conversion to unsigned types is preferred to conversion to signed types, and all arithmetic on short integers or characters implies conversion to int or longer.

Thus, for example, the value of (3/5)+2.1 is 2.1 because both the operands of the / are already the same type. The result of 3/5 is 0 because integer division truncates toward zero (if the quotient were negative, the implementation would have been permitted to truncate the quotient zero or toward , but both alternatives are equivalent for a positive quotient); that zero is then converted to double for addition to 2.1. As another example, although

   cout << ‘a’ << endl;

prints a,

   cout << (‘a’ + 0) << endl;

prints the integer that corresponds to a in the machine’s collating sequence, because addition converts its operands to int or longer.


Previous Table of Contents Next