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
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(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 asint
. If your number is too large, uselong long
. - Do not use plain
char
orbool
in arithmetic expressions. Use them only to hold characters or truth values. Computations usingchar
are especially problematic becausechar
issigned
on some machines andunsigned
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 bylong 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 non
bool
arithmetic type to abool
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 thebool
is trueAssigning 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 255Assigning 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
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 unsigned
and can never fail the condition
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
or0X
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
orU
can only be unsigned type which starts fromunsigned
tounsigned long long
. - Those with suffix
l, L, ll
orLL
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:
nonprintable characters
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;
}