What are the differences between int
, long
, long long
, and short
?
Between an unsigned
and a signed
type?
Between a float
and a double
?
Those types have different minimum sizes as listed in Table 2.1.
And additional rules are included in the language to impose some restraints on those types. Here are some rules:
int
will be not less than short
long
will be not less than int
long long
(C++11) will be not less than long
A signed
type can store positive or negative numbers (including zero).
A unsigned
type can only store non-negative numbers (i.e. numbers greater than or equal to zero).
The specified minimum precision of double
is greater than that of float
. Typically, float
s are represented in 32 bits, double
s in 64 bits.
To calculate a mortgage payment, what types would you use for the rate,
principal, and payment? Explain why you selected each type.
double
.
https://www.investopedia.com/mortgage/mortgage-rates/payment-structure/
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;
unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl; // 32
std::cout << u - u2 << std::endl; // -32 + 2^32
int i = 10, i2 = 42;
std::cout << i2 - i << std::endl; // 32
std::cout << i - i2 << std::endl; // -32
std::cout << i - u << std::endl; // 0
std::cout << u - i << std::endl; // 0
Write a program to check whether your predictions were correct. If not, study this section until you understand what the problem is.
#include <iostream>
int main()
{
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;
}
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
(a) 'a' (char), L'a' (wchar_t), "a" (char[]), L"a" (wchart_t [])
(b) 10 (int), 10u (unsigned), 10L (long), 10uL (unsigned long), 012 (int), 0xC (int)
(c) 3.14 (double), 3.14f (float), 3.14L (long double)
(d) 10 (int), 10u (unsigned), 10.(double), 10e-2(double)
a.1:'a'
is a character enclosed within single quotes that is a literal of type char
.
a.2: L'a'
is a character enclosed within single quotes and prefixed with a letter L
that is a literal of type wchar_t
.
a.3: "a"
is a character enclosed within double quotes that is a literal of type string
-- an array of constant char
s.
a.4 L"a"
is a character enclosed within double quotes and prefixed with a letter L
that is a literal of type wstring
-- an array of constant wchar_t
s.
b.1: By default, the decimal literals are signed and the smallest type in which the literal value 10
can fit is int
.
b.2: We override the default type of decimal literals by suffixing a letter u
to the undecorated literal 10
. It changes the signedness, the literal 10u
has an unsigned type. The smallest unsigned type in which the number 10
can fit is unsigned
.
b.3: ibid.
b.4: ibid.
b.5: 012
is an integer literal with a leading zero, we interpret this literal as octal. 012
in octal notation has a value of 10
(in decimal notation). The smallest unsigned type in which the number 10
can fit is int
.
b.6: ibid.
c.1: 3.14
is a floating-point literal that includes a decimal point(.
). The default type for floating-point literals is double
.
c.2: We override the default type of floating-point literals to float
by using the suffix f
.
c.3: ibid.
d.1: ibid.
d.2: ibid.
d.3: ibid.
d.4: 10e-2
is a floating-point literal that includes an exponent. The default type for floating-point literals is double
.
int month = 9, day = 7; // LINE 1
int month = 09, day = 07; // LINE 2
The variables day
in line 1 and line 2 have the same value of 7
in decimal notation.
In line 2, 09
is an invalid octal integer literal, because octal notation can only hold digits from 0
to 7
, and 9
is an invalid octal digit.
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
(a) \145
is a generalized escape sequence, which is a \
followed by three octal digits. The octal numeral 145
has the value of 101
(\(1 \times 8^2 + 4 \times 8^1 + 5 \times 8^0 = 101\)). ASCII table maps the number 101
to a lowercase letter e
.
The octal numeral 012
has the value of 10
, which represents a control character Line Feed(LF)
.
VALUE:
"Who goes with F\145rgus?\012"
is equivalent to "Who goes with Fergus?\n"
.
TYPE: array of constant char
(b)
VALUE: 31.4
TYPE: long double
(c)
1024f
is an invalid literal.
(d)
VALUE: 3.14
TYPE: long double
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.
#include <iostream>
// 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.
int main()
{
// HEX OCT CHR
// 32 062 '2'
// 4D 115 'M'
// 0A 012 '\n'
// 09 011 '\t'
std::cout << "\062\115\012" << std::endl; // OCT
std::cout << "\x32\x4D\x0A" << std::endl; // HEX
std::cout << "\062\x09\115\x0A" << std::endl; // MIXED
return 0;
}
Explain the following definitions. For those that are illegal, explain what’s wrong and how to correct it.
(a) std::cin >> int input_value;
(b) int i = { 3.14 };
(c) double salary = wage = 9999.99;
(d) int i = 3.14;
(a) Illegal. The right operand of >>
can't be a definition. Extract the definition into a single statement and put it before the statement in which >>
is included.
int input_value;
std::cin >> input_value;
(b) Illegal. It requires a narrowing conversion, which may lose data. Strip the outer curly braces off.
int i = 3.14;
(c) Illegal. Variable Names should be separated by commas. The rewritten statement is as follows:
double salary = 9999.99, wage = 9999.99;
(d) legal. It's a narrowing conversion of 3.14
from double
to int
. The fractional part is discarded, and only the integral part is kept.
What are the initial values, if any, of each of the following variables?
std::string global_str;
int global_int;
int main()
{
int local_int;
std::string local_str;
}
std::string global_str; // "" an empty string
int global_int; // 0
int main()
{
int local_int; // uninitialized
std::string local_str; // "" an empty string
}
Explain whether each of the following is a declaration or a definition:
(a) extern int ix = 1024;
(b) int iy;
(c) extern int iz;
(a) extern int ix = 1024; // Definition
(b) int iy; // Definition
(c) extern int iz; // Declaration
(a). Any declaration that includes an explicit initializer is a definition.
Which, if any, of the following names are invalid?
(a) int double = 3.14;
(b) int _;
(c) int catch-22;
(d) int 1_or_2 = 1;
(e) double Double = 3.14;
(a) int double = 3.14; // N, double is the reserved keyword
(b) int _; // Y
(c) int catch-22; // N, an identifier can't contain -(dash)
(d) int 1_or_2 = 1; // N, an identifier can't begin with a digit
(e) double Double = 3.14; // Y, identifiers are case-sensitive, Double is not the reserved keyword
What is the value of j in the following program?
int i = 42;
int main()
{
int i = 100;
int j = i;
}
j = 100;
The second assignment statement uses the local object named i(100)
rather than the global one.
Is the following program legal? If so, what values are printed?
int i = 100, sum = 0;
for (int i = 0; i != 10; ++i)
sum += i;
std::cout << i << " " << sum << std::endl;
Legal.
OUTPUT
100 45
The name i
defined in the scope of the for
statement hides the one defined outside the for
statement.
Which of the following definitions, if any, are invalid? Why?
(a) int ival = 1.01;
(c) int &rval2 = ival;
(b) int &rval1 = 1.01;
(d) int &rval3;
(a) Legal. We assign 1.01
to ival
.
(b) Legal. We bind the reference rval2
to ival
.
(c) Illegal. A reference may not be bound to a literal.
(d) Illegal. References must be initialized.
Which, if any, of the following assignments are invalid? If they are valid, explain what they do.
int i = 0 , &r1 = i;
double d = 0, &r2 = d;
(a) r2 = 3.14159;
(b) r2 = r1;
(c) i = r2;
(d) r1 = d;
(a) Valid. We assign 3.14159
to the object to which r2
refers, i.e., to d
.
(b) Valid. We assign the value of the object to which r1
refers (i.e. i
) to the object to which r2
refers (i.e. d
). In other words, we assign 0
to d
.
(c) Valid. We assign 3.14159
to i
. The value is truncated. i
has the value of 3
.
(d) Valid. ibid.
What does the following code print?
int i, &ri = i;
i = 5; ri = 10;
std::cout << i << " " << ri << std::endl;
10 10
ri
is an alias of i
.
We change the value of i
if we change ri
.
Write code to change the value of a pointer. Write code to change the value to which the pointer points.
#include <iostream>
// Write code to change the value of a pointer. Write code to change the value
// to which the pointer points.
int main()
{
int a = 100;
int *p = nullptr;
p = &a; // change the value of a pointer
*p = 1000; // change the value to which the pointer points
std::cout << *p << std::endl;
return 0;
}
Explain the key differences between pointers and references.
Similarities
Differences
What does the following program do?
int i = 42;
int *p1 = &i;
*p1 = *p1 * *p1;
int i = 42; // assign 42 to `i'
int *p1 = &i; // `p' holds the address of `i'; `p' is a pointer to `i'
*p1 = *p1 * *p1; // square the value of the object to which `p' points, i.e. `i'
Explain each of the following definitions. Indicate whether any are illegal and, if so, why.
int i = 0;
(a) double* dp = &i;
(b) int *ip = i;
(c) int *p = &i;
(a) Illegal. There is a mismatch between the type of dp
and the object to which dp
points.
(b) Illegal. We cannot assign an int variable to a pointer.
(c) Legal.
Assuming p
is a pointer to int, explain the following code:
if (p) // ...
if (*p) // ...
if (p) // check the value of p; 0/NULL/nullptr -> false; otherwise -> true
if (*p) // check the value of the object to which p points; 0 -> false; nonzero -> true
Given a pointer p
, can you determine whether p
points to a valid object? If so, how? If not, why not?
NO. There is no way to distinguish a valid address from an invalid one.
Why is the initialization of p
legal but that of lp
illegal?
int i = 42; void *p = &i; long *lp = &i;
A void*
pointer can hold the address of any type.
The type of lp
doesn't match the type of i
.
Determine the types and values of each of the following variables.
(a) int* ip, i, &r = i; (b) int i, *ip = 0; (c) int* ip, ip2;
(a)
ip
: a pointer to int
, undefined
i
: int
, undefined
r
: a reference to int
i
(b)
i
: int
, undefined
ip
: a pointer to int
, NULL
(c)
ip
: a pointer to int
ip2
: int
Which of the following are legal? For those that are illegal, explain why.
(a) const int buf; (b) int cnt = 0;
(c) const int sz = cnt; (d) ++cnt; ++sz;
(a) Illegal. A const object must be initialized.
(b) Legal.
(c) Legal.
(d) ++cnt
is legal. ++sz
is illegal, because const objects cannot be changed.
Which of the following initializations are legal? Explain why.
(a) int i = -1, &r = 0;
(b) int * const p2 = &i2;
(c) const int i = -1, &r = 0;
(d) const int * const p3 = &i2;
(e) const int * p1 = &i2;
(f) const int &const r2;
(g) const int i2 = i, &r = i;
(a) The first half is legal, but the second one is illegal.
(b) Legal. p2
is a const pointer.
(c) Legal. We can bind a reference to const to a literal.
(d) Legal. p3
is a const pointer to a const object
(e) Legal. p1
is a pointer to a const object.
(f) Illegal. We cannot define a const reference; references must be initialized.
(g) Legal.
Explain the following definitions. Identify any that are illegal.
(a) int i, * const cp;
(b) int * p1, * const p2;
(c) const int ic, &r = ic;
(d) const int * const p3;
(e) const int * p;
(a) N, a const pointer must be initialized.
(b) N, ID.
(c) N, ic must be initialized. r is a reference to a const object.
(d) N, p3 is a const pointer to a const object. ID.
(e) Y, p is a pointer to a const object.
Using the variables in the previous exercise, which of the following assignments are legal? Explain why.
(a) i = ic;
(b) p1 = p3;
(c) p1 = ⁣
(d) p3 = ⁣
(e) p2 = p1;
(f) ic = * p3;
(a) Y.
(b) N. p3
is a pointer to a const object.
(c) N. ic
is a const object.
(d) N. We cannot rebind a const pointer to a new object.
(e) N. ID.
(f) N. A const object's value can not be changed.
For each of the following declarations indicate whether the object being declared has top-level or low-level const.
const int v2 = 0;
int v1 = v2;
int * p1 = &v1, &r1 = v1;
const int * p2 = &v2, * const p3 = &i, &r2 = v2;
v2
: TOP
v1
: NONE
p1
: NONE
r1
: NONE
p2
: LOW
p3
: TOP, LOW
r2
: LOW
Given the declarations in the previous exercise determine whether the following assignments are legal. Explain how the top-level or low-level const applies in each case.
r1 = v2;
p1 = p2; p2 = p1;
p1 = p3; p2 = p3;
r1 = v2; // ok: copying the value of v2, top-level const in v2 is ignored
p1 = p2; // no: p2 has a low-level const but p1 doesn't
p2 = p1; // ok: we can convert int* to const int*
p1 = p3; // no: p3 has a low-level const but p1 doesn't
p2 = p3; // ok: p2 has the same low-level const qualification as p3
Is the following code legal or not? If not, how might you make it legal?
int null = 0, *p = null;
It is illegal to assign an int variable to a pointer, even if the variable's value happens to be 0.
Assign nullptr
to p
.
Using the variable definitions from this section, determine what happens in each of these assignments:
a = 42;
b = 42;
c = 42;
d = 42;
e = 42;
g = 42;
a = 42; // OK
b = 42; // OK
c = 42; // OK
d = 42; // NO, we cannot assign an int to a pointer
e = 42; // NO, ID.
g = 42; // NO, we cannot change the value of const reference.
Determine the types deduced in each of the following definitions. Once you’ve figured out the types, write a program to see whether you were correct.
const int i = 42;
auto j = i;
const auto &k = i;
auto * p = &i;
const auto j2 = i, &k2 = i;
const int i = 42;
auto j = i; // int
const auto &k = i; // const int &
auto * p = &i; // const int *
const auto j2 = i, &k2 = i; // const int, const int &
In the following code, determine the type of each variable and the value each variable has when the code finishes:
int a = 3, b = 4;
decltype(a) c = a;
decltype((b)) d = a;
++c; ++d;
a: int 4
b: int 4
c: int 4
d: int & 4
Assignment is an example of an expression that yields a reference type. The type is a reference to the type of the left-hand operand. That is, if i is an int, then the type of the expression i = x is int&. Using that knowledge, determine the type and value of each variable in this code:
int a = 3, b = 4;
decltype(a) c = a;
decltype(a = b) d = a;
a: int 3
b: int 4
c: int 3
d: int & 3
Describe the differences in type deduction between decltype and auto. Give an example of an expression where auto and decltype will deduce the same type and an example where they will deduce differing types.
Both auto
and decltype
can deduce the type from a expression.
auto
evaluates the expression as an initializer and assigns the return value to the variable.
decltype
allows us to not use the expression to initialize the variable and even not evaluate the expression.
decltype
deduces a reference type if the expression returns a left value.
decltype
deduces a reference type if the variables is a reference type.
For a reference type, auto
deduces a type of the object that the reference refers to.
Types deduced by decltype
keep top-level const
.
Types deduced by auto
doesn't keep top-level const
.
手机扫一扫
移动阅读更方便
你可能感兴趣的文章