练习 2.1
Q: 类型 int,long,long long 和 short 的区别是什么, 无符号和带符号类型的区别是什么? float 和 double 的区别是什么?
A:int, long, long long 和 short 尺寸不同, 表示的数据范围不同. 无符号只能表示 0 和正数, 无符号还可以表示负数. float 为单精度浮点数, double 为双精度, 一般来说, float 占 4 字节, double 占 8 字节.
练习 2.2
Q: 计算按揭贷款时, 对于利率, 本金和付款分别应选择何种数据类型? 说明你的理由.
A: 利率应该用 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: 指出下面字面值的数据类型
A:(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: 下面两组定义是否有区别?
- A:
- 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: 下述字面值表示什么含义? 各自的数据类型是什么?
A:(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, 最后转到新的一行.
- A: cout <<"\62\115\012" ;
- cout << "\62\t\115\012" ;
练习 2.9
Q: 解释下列定义的含义. 对于非法的定义, 说明错在何处
A:(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: 下列变量的初始值是什么?
- A:std::string g_str; // 初始化为一个空串
- int g_int; // 初始化为 0
- void test210 ()
- {
- int local_int; // 按标准局部变量不初始化, g++ 编译器下可能也会初始化为空
- std::string local_str;
- }
练习 2.11
Q: 指出下面的语句是被声明还是定义.
- A: (1)extern int ix = 1024; // 定义 (任何包含了显式初始化的声明即成为定义)
- (2)int iy; // 声明并定义 (想声明而不定义, 就在变量名前家 extern)
- (3)extern int iz; // 声明
练习 2.12
Q: 请指出下面的名字中哪些是非法的?
- A: (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 的值是多少?
- A:int i =42;
- void test213 ()
- {
- int i = 100;
- int j = i;
- cout <<"j =" << j << endl; //j =100 , 使用局部变量 j.
- }
练习 2.14
Q: 下面的程序合法吗? 输出什么?
- A: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: 下面哪个定义是不合法的, 为什么?
- A: (1)int ival = 1.01; // 用 float 初始化 int, 不合法, 会有警告
- (2)int &rval1 = 1.01; // 非法, 引用的初始值必须是一个对象
- (3)int &rval2 = ival; // 合法
- (4)int &rval3; // 非法, 引用必须被初始化.
练习 2.16
Q: 下面哪些赋值不合法, 为什么?
- A: 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: 下面的代码会输出什么结果?
- A: int i, &ri = i;
- i = 5;
- ri = 10;
- cout << "i =" << i << "ri =" << ri << endl; //i = 10, ri = 10 --- 改变 ri 的值也会改变 i 的值.
练习 2.18
Q: 编写代码分别更改指针的值以及指针所指对象的值.
- A: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: 说明指针和引用的主要区别.
A:(1) 引用在定义时必须初始化, 而指针可不初始化
(2) 引用在其生命周期内, 只能指向一个对象, 而指针可以先后指向不同的对象
(3) 指针本身就是一个对象, 允许对指针进行赋值和拷贝.
练习 2.20
Q: 叙述下面代码的作用
- A:int i = 42;
- int * p = &i;
- *p = *p * *p; // 42*42, 求 i 的平方.
练习 2.21
Q: 解释下述定义是否非法.
- A: int i = 0;
- (1)double* dp = &i; // 非法, 不能用 int 型的变量初始化 doube 指针
- (2)int* ip = i; // 非法, 不能用 int 值初始化指针
- (3)int* p = &i; // 合法
练习 2.22
Q: 假设 p 是一个 int 型指针, 说明下面代码的含义
- A: if (p) // 如果地址不为 0
- if (*p) // 如果所指的值为真
练习 2.23
Q: 给定指针 p, 能否知道它指向了一个合法的对象?
A: 不行, 如果你把指针理解为一个信封上的地址, 那么没有任何手段能保证你填写的地址必然有人住.(别人的回答)
我的理解, 给定一个指针, 首先要判断这个指针是否有效 (不为 NULL, 地址合法等), 好像没什么办法判断指向了合法对象, 有可能在使用过程中发现.
练习 2.24
Q: 下面的代码中, 为什么 p 合法而 lp 非法?
- A: 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 = // 合法
- (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:
A:
练习 2.40
Q:
A:
练习 2.41
Q:
A:
练习 2.42
Q:
A:
来源: http://www.bubuko.com/infodetail-2614963.html