c++ Primer 第五版習題答案第二章


練習2.1

Q: 類型int、long、long long和short的區別是什么,無符號和帶符號類型的區別是什么?float和double的區別是什么?

int、 long、 long long和short尺寸不同,表示的數據范圍不同。無符號只能表示0和正數,無符號還可以表示負數。float為單精度浮點數,double為雙精度,一般來說,float占4字節,double占8字節。

練習2.2

Q: 計算按揭貸款時,對於利率、本金和付款分別應選擇何種數據類型?說明你的理由。

利率應該用unsigned double表示,本金和付款應使用unsigned float表示。因為利率一般小數位數較多,且沒有負數,本金和付款小數位數少,也沒有負數。

 

練習2.3

Q: 讀程序,寫結果

  unsigned u = 10, u2 = 42; 
   std::cout << u2 - u << std::endl; //32
   std::cout << u - u2 << std::endl; // -32的補碼 4294967264
   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

練習2.5

Q:指出下面字面值的數據類型

(1)'a'<字符字面值>, L'a'<寬字符字面值,類型是wchar_t>, "a"<字符串字面值>, L"a"<寬字符字符串字面值(2)10<十進制>, 10u<無符號整型>, 10L<長整型>, 10uL<無符號長整型>, 012<八進制>, 0xC<十六進制(3)3.14,<浮點數> 3.14f<單精度浮點型字面值,類型是float>, 3.14L<擴展精度浮點型字面值,類型是long double>

(4)10<十進制>, 10u<無符號整型>, 10.<浮點型>, 10e-2<浮點型字面值>

練習2.6

Q:下面兩組定義是否有區別?

int month = 9, day = 7;    //定義的month和day均為10進制
int month = 09, day = 07;  // 定義的month和day為八進制,month會報錯,因為09超出范圍了。error: invalid digit '9' in octal constant

練習2.7

Q:下述字面值表示什么含義?各自的數據類型是什么?

(1)"who goes with F\145rgus?\012"   
   // \145表示小寫字母“e”, \012表示換行符。 輸出:who goes with Fergus?
(2) 3.14e1L   // 表示擴展的浮點型,類型是long double
(3) 1024f     // 單精度浮點型字面值,類型是float
(4) 3.14L     // 表示擴展的浮點型,類型是long double

練習2.8

Q:使用轉義寫一段程序,先輸出2M,然后轉到新的一行,修改程序使其先輸出2, 然后輸出制表符,再輸出M,最后轉到新的一行。

cout << "\62\115\012" ;
cout << "\62\t\115\012" ;

練習2.9

Q:解釋下列定義的含義。對於非法的定義,說明錯在何處

(1)std::cin >> int input_value     // 錯誤,不能在輸入輸出語句中定義變量。
(2)int i = { 3.14 };             // 錯誤,在初始化列表中使用浮點型初始化int變量可能會丟失數據,編譯器會拒絕執行
(3)double salary = wage = 9999.99; // wage未定義,如果wage定義了,則該語句可以正常執行,最終wage和salary相等
(4)int i = 3.14; // 警告,有隱式轉化,i值為3。

練習2.10

Q:下列變量的初始值是什么?

std::string g_str;    //初始化為一個空串
int g_int;      // 初始化為0
void test210 ()
{
int local_int; //按標准局部變量不初始化,g++編譯器下可能也會初始化為空
    std::string local_str;
}

練習2.11

Q:指出下面的語句是被聲明還是定義。

(1)extern int ix = 1024;  // 定義 (任何包含了顯式初始化的聲明即成為定義)
(2)int iy; // 聲明並定義 (想聲明而不定義,就在變量名前家extern)
(3)extern int iz; // 聲明

練習2.12

Q:請指出下面的名字中哪些是非法的?

(1)int doube = 3.14; //非法,double為關鍵字,不能作為變量名
(2)int _; //合法
(3)int catch-22; //非法,變量名只能包含字母、數字、下划線
(4)int 1_or_2 = 1; //非法,不能以數字開頭
(5)double Double = 3.14; //合法

練習2.13

Q:下面程序中j的值是多少?

int i =42;
void test213 ()
{
   int i = 100;
int j = i;
cout << "j = " << j  << endl; //j =100 ,使用局部變量j。
}

練習2.14

Q:下面的程序合法嗎?輸出什么?

int i =100, sum =0; 
for (int i =0; i != 10; ++i) {
 sum += i;
}  
cout << i << " " << sum << endl;  
// i = 100, sum = 45,for循環中的i,只在循環體內起作用,因此輸出的是全局變量i= 100, 局部變量sum依舊在作用域內,因此輸出局部變量sum=45。

練習2.15

Q:下面哪個定義是不合法的,為什么?

(1)int ival = 1.01;  //用float初始化int,不合法,會有警告
(2)int &rval1 = 1.01; //非法,引用的初始值必須是一個對象
(3)int &rval2 = ival; //合法
(4)int &rval3; //非法,引用必須被初始化。

練習2.16

Q:下面哪些賦值不合法,為什么?

int i = 0, &rl = i;
double d = 0, &r2 = d;

(1)r2 = 3.14159; //合法,d的值也變為3.14159
(2)r2 = r1; //合法,但隱式轉化
(3)i = r2; //合法,但隱式轉化
(4)r1 = d; //合法,但隱式轉化

練習2.17

Q:下面的代碼會輸出什么結果?

int i, &ri = i;
i = 5;
ri = 10;
cout << "i = " << i << "   ri = " << ri << endl;
//i = 10, ri = 10 --- 改變ri的值也會改變i的值。

練習2.18

Q:編寫代碼分別更改指針的值以及指針所指對象的值。

int i =20;
int j = 10;
int* p = &i;

cout << "p = " << p << endl; // p = 0x7ffee3a3ea3c
p = &j;
cout << "p = " << p << endl; // p = 0x7ffee3a3ea38
*p = 5;
cout << "*p = " << *p << " i = " << i  << " j = " << j << endl;
// *p = 5 i = 20 j = 5

練習2.19

Q:說明指針和引用的主要區別。

(1) 引用在定義時必須初始化,而指針可不初始化
(2)引用在其生命周期內,只能指向一個對象,而指針可以先后指向不同的對象
(3)指針本身就是一個對象,允許對指針進行賦值和拷貝。

練習2.20

Q:敘述下面代碼的作用

int i = 42; 
int * p = &i;
*p = *p * p; // 4242, 求i的平方。

練習2.21

Q: 解釋下述定義是否非法。

int i = 0;  
(1)double* dp = &i; //非法,不能用int型的變量初始化doube指針
(2)int* ip = i; //非法, 不能用int值初始化指針
(3)int* p = &i; //合法

練習2.22

Q: 假設p是一個int型指針,說明下面代碼的含義

if (p) //如果地址不為0

​if (*p) //如果所指的值為真

練習2.23

Q: 給定指針p,能否知道它指向了一個合法的對象?

不行,如果你把指針理解為一個信封上的地址,那么沒有任何手段能保證你填寫的地址必然有人住。(別人的回答)

我的理解,給定一個指針,首先要判斷這個指針是否有效(不為NULL,地址合法等),好像沒什么辦法判斷指向了合法對象,有可能在使用過程中發現。

練習2.24

Q: 下面的代碼中,為什么p合法而lp非法?

int i = 42;
void *p = &i; //因為void指針類型可以存放任意對象的地址
long *lp = &i; //但是long指針,就只能存放long對象的地址

練習2.25

Q: 說明下列變量的類型和值。

A:

(1) int* ip, i, &r = i;  // ip 為int指針類型,i為int型,r為引用類型,初始化為i。
(2) int i, *p =0; // i為int型, p為int指針類型,初始化為0,並未指向任何對象
(3) int* ip, ip2; // ip為int指針類型,ip2為int型

練習2.26

Q: 下面哪些句子是合法的,說明原因。

A:

(1)const int buf;  // 不合法,聲明一個const常量的同時必須初始化
(2)int cnt = 0; // 合法,聲明並初始化一個int變量
(3)const int sz = cnt; // 合法,聲明一個int const常量,並初始化。
(4)++ cnt; ++sz; // 不合法,sz為常量,不能進行++操作。

練習2.27

Q: 下面哪些初始化是合法的,說明原因。

A:

(1)int i = -1, &r = 0;   // 不合法, r為引用,初始化只能指向一個對象。
(2)int *const p2 = &i2; // 合法,定義一個int型的常量指針,初始化為i2的地址,之后指針的值不能再改變
(3)const int i = -1, &r = 0; // 合法, r為引用,const int &r = 0; 是合法的。(感謝評論去指正)
(4)const int* const p3 = &i2; // 合法,p3的值不能改變,*p3也不能改變
(5)const int* p1 = &i2; // 合法,指針常量,p1指向的值不能被改變
(6)const int& const r2; // 不合法,引用不能是const
(7)const int i2 = i, &r = i; // 合法

練習2.28

Q: 下面哪些是合法的,請說明。

A:

(1) int i, *const cp;  // 不合法,定義const類型指針要初始化,cp
(2) int *p1, *const p2; // 不合法,同上,p2應該初始化。
(3) const int ic, &r = ic; // 不合法,ic為const類型,必須要初始化
(4) const int *const p3; // 不合法,p3需要初始化
(5) const int *p; // 合法,指向是常量,但指針的值可變。

練習2.29

Q: 假設已有上題中所定義的變量,則下面哪些是合法的?

A:

(1) i = ic;   // 合法
(2) p1 = p3; // 不合法,int* 不能用const int* 初始化
(3) p1 = // 不合法,p1是一個普通指針,不能指向const int類型的值。
(4) p3 = // 不合法,p3的值和p3指向的值都不能改變
(5) p2 = p1; // 不合法,p2的值不能被改變
(6) ic = *p3; // 不合法,ic是常量,不能被改變

練習2.30

Q: 對於下面的語句,請說明對象被聲明為頂層const還是底層const。

A:

(1) const int v2 = 0; int v1 = v2;   // v2是頂層const
(2) int *p1 = &v1, &r1 = v1; // 非const
(3) const int *p2 = &v2, *const p3 = &i, &r2 = v2; // p2是底層const,p3最左是底層,p3前面是頂層const, r2是底層const。

練習2.31

Q: 假設上題中的變量已定義,判斷下面語句哪些合法。

A:

(1) r1 = v2;  // 合法,引用改變值
(2) p1 = p2; p2 = p1; // 不合法,p2是底層const,賦值對象必須同樣有底層const才行,p2 = p1合法
(3) p1 = p3; p2 = p3; // 不合法,p3是底層const, p2 = p3合法。

總結:頂層const可以進行賦值操作。但底層const有限制,拷入拷出的對象也必須具有相同的底層const。

練習2.32

Q: 下面的代碼是否合法?說明原因。

A:

int null = 0, *p = null;        
// int *p不能用int型來初始化。 應為 int null = 0, *p = &null / int *p = nullptr

練習2.33

Q: 利用本節已定義的變量,判斷下列語句的運行結果。

A:

(1) a = 42; b = 42; c = 42;   // a, b, c的值均為42
(2) d = 42; e = 42; g = 42; // d:error, d為int *類型
// e:error, e為int*類型
// g:error, g為const int類型,不能再賦值

練習2.34

Q: 證明上述推斷是否正確,寫一段程序。

A:

int i = 0, &r = i; 
auto a = r;
const int ci = i, &cr = ci;
auto b = ci;
auto c = cr;
auto d = &i;
auto e = &ci;
auto &g = ci;

a = 42;
b = 42;
c = 42;
std::cout << a << b << c << std::endl;

>>    d = 42;
>>    e = 42;
>>    g = 42;

練習2.35

Q: 判斷下面定義的類型,編寫程序驗證。

A:

const int i = 42;  // i為const int類型
auto j = i; // j為int類型
auto &k = i; // k為const int& 類型
auto p = &i; // p為const int 類型
const auto j2 = i, &k2 = i; // j2為const int類型,k2為const int& 類型。

練習2.36

Q: 關於下列代碼,指出每個變量的值及程序結束后的值。

A:

 int a = 3, b = 4;  //
decltype(a) c = a; // c為int類型,a為c的初值
decltype((b)) d = a; // d為int& 類型,是a的引用
++c; // ++c之后的值為4;
++d; // ++d之后的值為4

練習2.37

Q: 賦值是會產生引用的一類典型表達式,引用的類型就是左值的類型。也就是說,如果i是int,則表達式i=x的類型是int&。根據該特點指出下面變量的類型。

A:

int a = 3, b = 4;  // a, b均為int
decltype (a) c = a; // c為int
decltype (a = b) d = a; // d為int&,是a的引用。

練習2.38

Q: 舉例說明decltype指定類型和auto有何區別。

A:

相同點:都通過已知變量或表達式的類型來指定類型。如:int i = 2; auto j = i; decltype(i) j = i; 兩者相同。不同點:(1)auto會忽略頂層const,但decltype不會。

(2)auto定義變量必須有初始值,但decltyple不一定

練習2.39

Q: 編譯下面程序觀察其運行結果,注意,如果忘記寫類定義體后面的分號會發生什么情況?記錄下相關信息,以后可能會有用。

struct Foo {/*此處為空*/} //注意:沒有分號
int main()
{
   return 0;
}

報錯:error: expected ';' after struct definition

練習2.40

Q: 根據自己的理解寫出Sales_data類,最好與書中的例子有所區別。

struct Sales_data
{
   string bookNo;
   unsigned units_sold = 0;
   double revenue = 0.0;
};

練習2.41

Q: 使用你自己的Sales_data類重寫1.5.1節、1.5.2節和1.6節的練習。眼下先把Sales_data類的定義和main函數放在同一個文件里。

A:

練習2.42

Q:根據自己的理解重寫一個Sales_data.h頭文件,並以此為基礎重做2.6.2節的聯系。

A:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM