1. 程式人生 > >C++Primer Section 2-1

C++Primer Section 2-1

Section 2-1 Primitive Built-in Types

The set of primitive built-in types are arithmetic types and a special type void.

Section 2-1-1 Arithmetic Types

Arithmetic types include characters, integers, boolean values and floating-point numbers.

But it can be divided into two categories—integers types

and floating-point types.

Size of different types depends on machines. But the table gives the minimum size of each type.

Type Meaning Minimum Size
bool boolean NA
char character 8 bits
wchar_t wide character 16 bits
char16_t Unicode character 16 bits
char32_t Unicode character 32 bits
short short integer 16 bits
int integer 16 bits
long long integer 32 bits
long long long integer 64 bits
float single-precision floating-point 6 significant digits
double double-precision floating-point 10 significant digits
long double extended-precision floating-point 10 significant digits

Differences in Integer Types

Integer types include bool,char,wchar_t,char16_t,char32_t,short,int,long,long long.

Differences between char, wchar_t, char16_t and char32_t

char is guaranteed to be big enough to hold the basic set of characters in a machine, while wchar_t is guaranteed to be big enough to hold any character in the machine’s largest extended character set.

char16_t and char32_t are intended for Unicode characters.

Note

Sometimes the compiler will replace char by wchar_t or char16_t, char32_t.

Differences between short, int, long and long long

These four types are all intended for integers. The only difference between them is the size of them and the range of the number that they can represent.

But in different machines, those sizes and ranges change. But basically, we have the following rule:

sizeof(short)`sizeof(int)`sizeof(long)sizeof(long long)

Differences between in Floating-point Types

Differences between float, double and long double

These three types are all intended for floating-point number.

They have different sizes, precisions and purposes. Usually, float are represented in 1 word(32 bits). double in two words(64 bits) and long double in 3 or 4 words(96 or 128 bits).

The float and double types typically yield about 7 and 16 significant digits, respectively.

The type long double is often used as a way to accommodate special-purpose floating-point hardware.

Signed and Unsigned Types

Except for bool and the extended character types,, the integral types may be signed or unsigned.

A signed value can represent both negative an positive numbers by using special method. But an unsigned value can represent only 0 and positive numbers. and all bits in it represent the value.

int,short,long, long long are all signed types. To get corresponding unsigned types, we add unsigned to the type like unsigned long long.

unsigned int can be abbreviated as unsigned.

For characters, it is a little tricky since there will be three types char, singed char and unsigned char. But there are only two ways of representation signed and unsigned. Which type of representation char will take depends on the compiler.

Some people say that unsigned types are used to precisely control the machine-level or circuit-level operations instead of to enlarge the range of numbers that can be represented.

Good Practices for Using Arithmetic Types

  • Use an unsigned type when you know that the values cannot be negative
  • Use int for integer arithmetic. short is usually too small and , in practice, long often has the same size as int. If your number is too large, use long long.
  • Do not use plain char or bool in arithmetic expressions. Use them only to hold characters or truth values. Computations using char are especially problematic because char is signed on some machines and unsigned on others.
  • Use double for floating-point computations; float usually does not have enough precision, and the cost of double-precision calculations versus single-precision is negligible. In fact, on some machines, double-precision operations are faster than single. The precision offered by long double is usually unnecessary and often entails considerable run-time cost.

Exercises

Exercise 2.1

What are the differences between int, long, long long and short? Between an unsigned and signed type? Between a float and double?

Solution

In part Differences in Integer Types and Differences in Floating-point Types

Exercise 2.2

To calculate a mortgage payment, what types would you use for the rate, principle, and payment? Explain why you selected each type.

Solution

All shall be double. All of them may be floating-point number and for floating-point computations we use double.

Section 2-1-2 Type Conversions In Assignment Statements

Type conversions take place wherever we expected one type of value while given another related type of value.

Basic Rules for Type Conversions in Assignment Statements

  • Assigning a nonbool arithmetic type to a bool type:

    result is false if the value is 0 and true otherwise

  • Assigning a bool to another arithmetic type of value:

    the result is 0 if the bool is false and 1 if the bool is true

  • Assigning a floating-point value to an object of integral type:

    The value will be truncated.

  • Assigning an integral value to an object of floating-point type

    Fraction part is 0. Precision may be lost if the integer has more bits than floating-point object can accommodate.

  • Assigning an out-of-range value to an object of unsigned type

    The result is the remainder of the value modulo the number of values the target type can hold. For example -1 to unsigned char will be 255

  • Assigning an out-of-range value to an object of signed type, the result is undefined.

Advice on how to use Type Conversions: Avoid undefined and implementation-Defined Behavior

Undefined behavior results from errors that the compiler is not required or able to detect, like the overflow of signed type. But this depends on the compiler, input and so on. So sometimes the program may work under a particular circumstance but fails under another.

Implementation-defined Behavior is about the portability of the program, meaning that when a program is moved from one platform to another, whether it can work as well as before. It has something to do with the features that vary between different platforms like the size of int.

A Typical Use of Type Conversion—Integer in Condition

int i = 0;

do something;

if (i) {
    do something;
}

In the block of code above. we have that the condition will evaluate as true is i0. And the condition will evaluate as false if i=0.

But it is worth noting that using bool in an arithmetic expression is highly NOT recommended.

Expressions Involving Unsigned Types

Arithmetic Expressions

If we use both an int and unsigned value in an arithmetic expression, the int will be converted to unsigned even if it is negative.

unsigned u = 10;
int i = -42;
std::cout << i + i << std::endl; // prints -84
std::cout << i + u << std::endl; // if 32-bit ints, prints 4294967264

So it is also important not to make the result of subtraction of unsigned negative.

unsigned u1 = 42, u2 = 10;
std::cout << u1 - u2 << std::endl;  // result is 32
std::cout << u2 - u1 << std::endl;  // result is -32 % MAX
Unsigned Type in Loop Condition
for (unsigned i = 10; i >= 0; i--) {    // intended to execute for 11 times but fails
    do something;
}

This loop shall never terminate because i is unsigned and can never fail the condition i0. But we can still do the following to compensate for it.

for (unsigned i = 11; i > 0; i++) {     // intended to execute for 11 times and succeed
    do something;
}
Tips On Using unsigned and signed

Do NOT mixed signed and unsigned Types!

signed value will be automatically converted to unsigned value. So mixing signed and unsigned type will yield surprising and even unpredictable results, especially when signed value is negative.

Exercise 2.3

What output will the following code produce?

unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl;
std::cout << u - u2 << std::endl;

int i = 10, i2 = 42;
std::cout << i2 - i << std::endl;
std::cout << i - i2 << std::endl;

std::cout << i - u << std::endl;
std::cout << u - i << std::endl;
Solution

The output should be

32

-32 % MAX

32

-32

0

0

MAX stands for the max number of unsigned + 1.

Exercise 2.4

Write a program to check whether your predictions were correct. If not, study this section until you understand what the problem is.

Solution

The solution to 2.3 is right. And 32 % MAX is 4294967264.

Section 2-1-3 Literals

A literal refers to a value like 42 whose value is self-evident. Every literal has a type. The form and value will determine its type.

And we have three tables for the form of literal and the type of literals.

Table 1: Character and Character String Literals
Prefix Meaning Type
u Unicode 16 character char16_t
U Unicode 32 character char32_t
L wide character wchar_t
u8 utf-8(string literals only) char
Table 2: Integer Literals
Suffix Minimum Type
u or U unsigned
l or L long
ll or LL long long
Table 3: Floating-Point Literals
Suffix Type
f or F float
l or L long double

Actually, there is no negative literals because although the literal -42 seems a negative literal, it is actually composed of an operator - and a positive literal 42.

Integer and Floating-Point Literals

Integer Literals

We can write integer literals using decimal, octal or hexadecimal notation.

  • Integer literals that begin with 0 are interpreted as octal
  • Those that begin with either 0x or 0X are interpreted as hexadecimal
  • Decimal is decimal

For example

12      // decimal
012     // octal
0x14    // hexadecimal
How to determine integer literals’ type
  • A decimal literal has the smallest type of int, long, long long in which the literal’s value fits.
  • A octal or hexadecimal literal has the smallest type of int, unsigned, long, unsigned long, long long, unsigned long long in which the literal’s values fits.
  • No integer type has the type short
  • Those with suffix u or U can only be unsigned type which starts from unsigned to unsigned long long.
  • Those with suffix l, L, ll or LL has a minimum type as in the Table 2.
Tips on using suffix of integer literals

Use L instead of l which can be easily mistaken for 1.

Floating-Point Literals

We can write floating-point literals in two forms—normal notation with a decimal point or scientific notation with an exponent indicated by e or E.

For example

3.1415926    0.0     0e0     3.1E-4     0.    .1
How to determine a floating-point literal’s type
  • By default, they have the type double.
  • Every floating-point literal with suffix have its type determined by suffix as in Table 3.

Character and Character String Literals

Character Literals

A character enclosed within single quotes is a character literal.

How to determine a character literal’s type
  • By default, it has the type char.
  • Every character literal with prefix have its type determined by prefix as in Table 1.
Character String Literals

Zero or more characters enclosed within double quotation marks is a string literal.

  • The size of a string literal is one more than its apparent size with additional invisible character '\0' at the end of the string literal.

  • 'A' is different from "A".

  • Two string literals that appear adjacent to one another and that are separated only by spaces, tabs, or newlines are concatenated into one literal.

    For example

    std::cout << "a really, really long string literal "
            "taht spans two lines" << std::endl;

Escape Sequence

Two kinds of characters are in need of escape sequence:

  1. nonprintable characters

  2. characters with special purpose in language.

    For example

    // nonprintable
    \n       // newline
    \t       // horizontal tab
    \a       // alert(bell)
    \b       // backspace     
    // special purpose in language
    \\       // backslash
    \"       // double quote
    \'       // single quote    

In code

std::cout << '\n';  // a newline
std::cout << "\tHi!\n";     // a tab followed by Hi! followed by a newline
Generalized Escape Sequence

We can use generalized escape sequence, which is \x followed by one or more hexadecimal digits or a \ followed by one, two or three octal digits. The value represents the numerical value(usually ASCLL) of the character.

For example

\7      // bell
\12     // newline
\40     // blank
\0      // null
\115    // 'M'
\x4d    // 'M'    

In code

std::cout << "Hi \x4dO\115!\n";     // prints    Hi MOM! followed by a newline
std::cout << '\115' << '\n';        // prints    M followed by a newline

Boolean and Pointer Literals

Boolean Literals

true and false

Pointer Literals

nullptr

Exercises

Exercise 2.5

Determine the type of each of the following literals. Explain the differences among the literals in each of the four examples:

(a). 'a', L'a', "a", L"a"

(b). 10, 10u, 10L, 10uL, 012, 0xC

(c). 3.14, 3.14f, 3.14L

(d). 10, 10u, 10., 10e-2

Solution

(a) The first two are character literals and the last two are character string literals with two characters.

'a'     // type char
L'a'    // type wchar_t
"a"     // type const char*
L"a"    // type const wchar_t *    

(b) The first four are decimal literals and 012 is octal literal and 0xC is hexadecimal literal.

10      // int
10u     // unsigned int
10L     // long
10uL    // unsigned long    
012     // int
0xC     // int    

(c) They are all floating-point literals

3.14    // double
3.14f   // float
3.14L   // long double   

(d) The first two are integer literals and the last two are floating-point literals

10      // int
10u     // unsigned
10.     // double
10e-2   // double    
***Exercise 2.6

What, if any, are the differences between the following definitions:

int month = 9, day = 7;
int month = 09, day = 07;
Solution

The 09 seems an octal literal but there ought to be no 9 in octal literal. And 07 , though it is an octal literal, it does not make any difference. I was a little confused so I wrote a program and executed it.

The result is

2-6.cpp:5:14: error: invalid digit “9” in octal constant
int month = 09;
^

So this kind of expression is actually illegal.

Exercise 2.7

What values do these literals represent? What type does each have?

(a). "Who goes with F\145rgus?\012"

(b). 3.14e1L

(c). 1024f

(d). 3.14L

Solution

(a). Who goes with Fergus? followed by a newline. const char * type

(b). 3.14 long double type

(c). 1024 float type

(d). 3.14 long double type

Exercise 2.8

Using escape sequences, write a program to print 2M followed by a newline. Modify the program to print 2, then a tab, then an M, followed by a newline.

Solution
#include<iostream>

int main()
{
    std::cout << "\62\115\12";
    std::cout << "\62\t\115\12";

    return 0;
}