天天看點

C++ primer(5e)第2章習題

2019.04.27第二遍

特别注意的地方

  1. 與其他整型不同,字元型被分成了三種:char、unsigned char、signed char。char是哪種是由編譯器決定的。
  2. 當我們賦給帶符号類型一個超出它表示範圍的值時,結果是未定義的。此時,程式可能繼續工作、可能崩潰、也可能産生垃圾資料。
  3. 類型short沒有對應的字面值。
  4. 十進制字面值不可能是負值,如有有個帶負号的字面值,那麼那個負号作用僅僅是對字面值取負值。
  5. 字元串字面值的實際長度要比它的内容多1 。
  6. 對象是指一塊能存儲資料并具有某種類型的記憶體空間。
  7. 初始化和指派是兩個完全不同的操作。
  8. 定義于任何函數體之外的變量被初始化為0,定于在函數體内部的内置類型變量将不被初始化。
  9. 用花括号來初始化變量被稱為清單初始化,這種初始化有一個重要特點:如果我們使用清單初始化且初始值存在丢失資訊的風險,則編譯器會報錯。
  10. 如果想聲明一個變量而非定義它,就在變量名前添加關鍵字extern,而且不要顯式地初始化變量。任何包含了顯示初始化的聲明即成為定義。
  11. 在函數體内部,如果試圖初始化一個由extern關鍵字标記的變量,将引發錯誤。
  12. 使用者自定義的辨別符中不能連續出現兩個下劃線,也不能以下劃線緊連大寫字母開頭。定義在函數體外的辨別符不能以下劃線開頭。
  13. 右值引用主要用于内置類。引用必須被初始化。引用類型的初始值必須是一個對象。
  14. 指針是對象且無須在定義時指派。不能定義指向引用的指針。
  15. 使用未經初始化的指針是引發運作時錯誤的一大原因。
  16. 如果利用一個對象去初始化另外一個對象,則它們是不是const都無關緊要。
  17. auto定義的變量必須有初始值;會忽略掉頂層const。
  18. decltype((variable))的結果永遠是引用。

2.1

1.一個int至少和一個short一樣大,一個long至少個一個int一樣大,一個long long 至少和一個long一樣大。
2.帶符号類型可以表示正數、負數或0,無符号類型則僅能表示大于等于0的值。
3.一般來說,float類型有7個有效位,double類型有16個有效位。
(float至少有6個有效位,double至少有10個有效位)
           

2.2

利率:double(float和double的計算代價相差不大,對于某些機器,double更快)
本金:long long (不清楚你是不是想買豪宅)
付款:long long (同上)
           

2.3

unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl;     // 32
std::cout << u - u2 << std::endl;     //  2^32 - 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
           

2.4

#include<iostream>
int main()
{
	unsigned u = 10, u2 = 42;
	int i = 10, i2 = 42;

	std::cout << u2 - u << std::endl;
	std::cout << u - u2 << std::endl;
	std::cout << i2 - i << std::endl;
	std::cout << i - i2 << std::endl;
	std::cout << i - u << std::endl;
	std::cout << u - i << std::endl;
	return 0;
}
           

運作結果如下

C++ primer(5e)第2章習題

2.5

(a) 'a', L'a', "a", L"a"   // 
 字元字面值:char ;寬字元型字面值: wchar_t;  字元串字面值 ; 寬字元串字面值  
 (b) 10, 10u, 10L, 10uL, 012, 0xC
 int , unsigned int , long , unsigned long, 八進制,16進制
 (c) 3.14, 3.14f, 3.14L
 double, float, long double
 (d) 10, 10u, 10., 10e-2
 int , unsigned int, 浮點型字面值, 科學計數法
           

2.6

int month = 9, day = 7;
int month = 09, day = 07;
有差別,上面的day為10進制,下面的day為8進制。
           

2.7

(a) 隻知道/145和/012構成轉義字元
(b)long double型加科學計數法 31.4
(c) float型1024.0
(d) long double型3.14
           

2.8

#include<iostream>
int main()
{
	std::cout << "2\x4d\n" << std::endl;
	std::cout << "2\t\x4d\n" << std::endl;
	return 0;
}
           

2.9

(a) 錯誤。未定義的input_value,改為 int input_value; std::cin >> input_value;
(b) 錯誤。從double到int 需要收縮變換
(c) =從右向左結合,wage未定義類型
(d) 可以運作。
           

2.10

std::string global_str;
int global_int;
int main()
{
	int local_int;
	std::string local_str;
}
定義于任何函數體之外的變量被初始化為0,故global_str = "0", global_int = 0。
定義在函數體内部的内置類型變量不被初始化,故local_int, local_str值未定義。
           

2.11

(a)定義
(b)聲明并定義
(c)聲明
           

2.12

(a)非法
(b)合法 
(c)非法
(d)非法
(e)合法
           

2.13

2.14

合法
輸出:100 45
for循環定義的i到結束循環就不能使用了,故i輸出為100
           

2.15

(a)不太好,但是可以。
(b)不合法,引用類型的初始值必須是一個對象
(c)合法
(d)不合法,引用必須被初始化
           

2.16

(a)給d指派為3.14159
(b)可以,不太好。把int類型的i的值賦給double類型d 
(c)不合法,
(d)不合法,r1的初始值必須為int型對象
           

2.17

2.18

#include<iostream>
int main()
{
	int i = 12;
	int *p = &i;
	// 修改指針的值
	std::cout << p << std::endl;
	p++;
	std::cout << p << std::endl;
	/* 修改指針所指對象的值
	std::cout << *p << std::endl;
	(*p)++;
	std::cout << *p << std::endl;
	*/
	return 0;
}
           

2.19

指針:允許指派和拷貝;在生命周期内可以指向不同對象;不需要在定義時賦初值。
引用: 不能定義引用的引用;定義引用時程式是把引用和它的初始值綁定在一起,不是拷貝;引用必須被初始化。
           

2.20

2.21

(a)非法,試圖把int型對象的位址賦給double型指針
(b)非法,不能把int變量直接賦給指針
(c)合法,把i的位址賦給指針ip
           

2.22

if(p) // ...         如果指針不為空,則進行下面的語句
if(*p) //...      如果指針指向的值不為空,則進行下面的語句
           

2.23

先用*p将指針所指對象的值輸出,如果報錯,則說明指針指向無效的對象,然後用if(p == NULL)進行判斷。
           

2.24

void*指針可用于存放任意對象的位址;而lp指針為long型,不能存在int類型的對象的位址。
           

2.25

(a)ip為int型指針,i為int型變量,r為對int型變量i的引用
(b)i為int型變量,ip為所指對象的值為0的int型指針
(c)ip為int型指針,ip2為int型變量
           

2.26

(a)不合法,const對象必須初始化
(b)合法
(c)合法
(d)++sz不合法   const對象不能改變值
           

2.27

(a)不合法,不能為非常量引用綁定字面值
(b)合法
(c)合法
(d)合法
(e)合法
(f)不合法,引用必須初始化
(g)不合法,這樣可通過修改r的值來修改i2的值
           

2.28

(a)i為int類型的變量,cp為int類型的常量指針
(b)p1為int類型指針,p2為int類型常量指針
(c)ic為int類型常量,r為整形常量引用
(d)p3為指向int類型常量的常量指針
(e)p為指向int類型常量的指針
           

2.29

(a)不合法,不能把常量賦給變量
(b)不合法,同上
(c)不合法,同上
(d)合法
(e)合法
(f)不合法,左邊應是變量,不能為常量
           

2.30

const int v2 = 0;  // 頂層const
int v1 = v2;      // 不合法
int *p1 = &v1, &r1 = v1;   //  沒有
const int *p2 = &v2, *const p3 = &i, &r2 = v2; // p2為底層const
   //p3靠右的為頂層const,靠左的為底層const
           

2.31

r1 = v2;    // 不合法
p1 = p2;    // 不合法
p2 = p1;    // 合法
p1 = p3;    // 不合法
p2 = p3;   // 不合法
           

2.32

不合法
int null = 0, *p = &null;
           

2.33

a = 42;    // 合法
b = 42;    // 合法
c = 42;    // 合法
d = 42;    // 不合法
e = 42;   // 不合法
g = 42;   // 不合法
           

2.34

C++ primer(5e)第2章習題

17、18、19行出現問題,說明我上一個習題推斷正确

2.35

const int i = 42;
auto j = i; const auto &k = i; auto *p = &i;
const auto j2 = i, &k2 = i;
(1)j是一個整數(i的頂層const特性被忽略掉了)
(2)k是一個整形常量引用
(3)p是一個指向int類型指針的指針
(4)j2是一個int類型的常量,k2是常量引用
           

程式如下:

#include<iostream>
int main()
{
	const int i = 42;
	auto j = i;
	const auto &k = i;
	auto *p = &i;
	const auto j2 = i, &k2 = i;
	std::cout << j << " " << k << " " << p << " "
		<< j2 << " " << k2 << std::endl;
	return 0;
}
           

2.36

int a = 3, b = 4;     
decltype(a) c = a;   
decltype ((b)) d = a;  
++c;      // c為int類型,值為4
++d;     // d為int&, 值為4
           

2.37

int a = 3, b = 4;
decltype(a) c = a;  // c為int類型,值為3
decltype(a = b) d = a;   // d為int&,值為4
           

2.38

差別:
decltype:如果decltype使用的表達式是一個變量,則decltype傳回該變量的類型(包括頂層const和引用在内)
auto:auto一般會忽略頂層const

例子:
一樣:int a = 3; decltype (a) b = a;   auto b = a;
不一樣:const int a = 3; decltype(a) b = a;  auto b = a;
           

2.39

C++ primer(5e)第2章習題

2.40

struct Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};
// 書上把想的寫出來了,“最好”兩字說明可以和書上一樣~
           
c++

繼續閱讀