目录
第三章 字符串、向量和数组
3.2 标准库类型string
3.10 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 , s2;
cin >> s1;
for(auto &c : s1)
{
if(!ispunct(c))
s2 += c;
}
cout << s2 << endl;
return 0;
}
3.11 下面的范围for语句合法吗?如果合法,c的类型是什么?
合法,c是const char类型。虽然对常量引用了,但是并没有改变常量。
3.3 标准库类型
3.3.1 定义和初始化vector对象
3.12 下列vector对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。
(a)vector<vector<int>> ivec;
(b)vector<string> svec = ivec;
(c)vector<string> svec(10, "null");
(a) 正确,创建了元素为vector的空vector容器
(b)错误,拷贝构造的元素类型不一样
(c)正确,创建了包含10个元素为null的vector容器
3.13 下列的vector对象各包含多少个元素?这些元素的值分别是多少?
vector<int> v1;
vector<int> v2(10);
vector<int> v3(10, 42);
vector<int> v4{ 10 };
vector<int> v5{ 10, 42 };
vector<string> v6{ 10 };
vector<string> v7{ 10, "hi" };
(a)包含0个元素;(b)包含10个元素,值都为0;
(c)包含10个元素,值都为42;(d)包含1个元素,值为10;
(e)包含2个元素,值为10,42;(f)包含10个元素,空字符串;(g)包含10个元素,值都为“hi”。
3.3.2 向vector对象中添加元素
3.14 编写一段程序,用cin读入一组整数并把它们存入一个vector对象。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> vec;
int i;
while (cin >> i)
{
vec.push_back(i);
}
return 0;
}
3.15 改写上题程序,不过这次读入的是字符串。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<string> vec;
string str_in;
int i = 0;
while (cin >> str_in)
{
vec.push_back(str_in);
cout << vec[i] << endl;
++i;
}
return 0;
}
3.3.3 其他vector操作
3.16 编写一段程序,把练习3.13中vector对象的容量和具体内容输出出来
#include <iostream>
#include <vector>
#include<string>
using namespace std;
int main()
{
vector<int> v1;
cout << v1.empty() << endl;
vector<int> v2(10);
cout << v2.size() << endl;
for(vector<int>::size_type i = 0 ; i < v2.size() ; ++i)
cout << v2[i] << " ";
cout << endl;
vector<int> v3(10, 42);
cout << v3.size() << endl;
for(vector<int>::size_type i = 0 ; i < v3.size() ; ++i)
cout << v3[i] << " ";
cout << endl;
vector<int> v4{10};
cout << v4.size() << endl;
for(vector<int>::size_type i = 0 ; i < v4.size() ; ++i)
cout << v4[i] << " ";
cout << endl;
vector<int> v5{10, 42};
cout << v5.size() << endl;
for(vector<int>::size_type i = 0 ; i < v5.size() ; ++i)
cout << v5[i] << " ";
cout << endl;
vector<string> v6{10};
cout << v6.size() << endl;
for(vector<string>::size_type i = 0 ; i < v6.size() ; ++i)
cout << v6[i] << " ";
cout << endl;
vector<string> v7{10, "hi"};
cout << v7.size() << endl;
for(vector<string>::size_type i = 0 ; i < v7.size() ; ++i)
cout << v7[i] << " ";
cout << endl;
return 0;
}
3.17 从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改为大写形式。输出改变后的结果,每个词占一行。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
vector<string> v;
string str_in;
while(cin >> str_in)
v.push_back(str_in);
for(auto &s : v)
{
for(auto &c : s)
c = toupper(c);
cout << s << endl;
}
return 0;
}
3.18 下面的程序合法吗?如果不合法,你准备如何修改?
vector<int> ivec;
ivec[0] = 42;
不合法,ivec.push_back(42);
3.19 如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?
vector<int> ivec1(10,42); //最好,大量重复值,简洁
vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector<int> ivec3 = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector<int> ivec4(ivec1);
vector<int> ivec4 = ivec1;
3.20 读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输入第二个和倒数第二个元素的和,以此类推。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
vector<int> v;
int a;
while (cin >> a)
v.push_back(a);
auto b = v.size();
for(decltype(b) i = 0 ; i < v.size() ; ++i)
cout << v[i] + v[i+1] << " ";
for(decltype(b) i = 0 ; i < b/2 ; ++i)
cout << (v[i] + v[b-i-1]) << " ";
return 0;
}
3.21 请使用迭代器重做3.3.3节的第一个练习。
#include <iostream>
#include <vector>
#include<string>
using namespace std;
int main()
{
vector<int> v1;
if(v1.begin() == v1.end())
cout << "v1为空" << endl;
vector<int> v2(10);
int i = 0;
for(auto it = v2.begin() ; it != v2.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v2的大小为: " << i << endl;
vector<int> v3(10, 42);
i = 0;
for(auto it = v3.begin() ; it != v3.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v3的大小为: " << i << endl;
vector<int> v4{10};
i = 0;
for(auto it = v4.begin() ; it != v4.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v4的大小为: " << i << endl;
vector<int> v5{10, 42};
i = 0;
for(auto it = v5.begin() ; it != v5.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v5的大小为: " << i << endl;
vector<string> v6{10};
i = 0;
for(auto it = v6.begin() ; it != v6.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v6的大小为: " << i << endl;
vector<string> v7{10, "hi"};
i = 0;
for(auto it = v7.begin() ; it != v7.end() ; ++it)
{
cout << *it << " ";
i++;
}
cout << endl;
cout << "v7的大小为: " << i << endl;
return 0;
}
3.25 3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<unsigned> scores(11 , 0);
unsigned grade;
auto it = scores.begin();
while (cin >> grade)
++*(it + grade/10);
for(auto s : scores)
cout << s << " ";
cout << endl;
return 0;
}
3.26 在100页的二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?
迭代器不能相加,而两个迭代器相减代表的是他们之间的距离。
3.5 数组
3.5.1 定义和初始化内置数组
3.27 假设txt_size 是一个无参函数,它的返回值是int。请回答下列哪个定义是非法的,为什么?
unsigned buf_size = 1024;
(a) int ia[buf_size];
(b) int ia[4 * 7 - 14];
(c) int ia[txt_size()];
(d) char st[11] = "fundamental";
(a) 、(c)不正确,数组的维度必须是一个常量表达式;
(d)不正确,没有空间存放空字符;
(b)合法。
3.28 下列数组中元素的值是什么?
string sa[10];
int ia[10];
int main() {
string sa2[10];
int ia2[10];
}
sa[10]和sa2[10]:空字符串
ia[10]和ia2[10]:0
3.29 相比于vector 来说,数组有哪些缺点,请例举一些。
数组的大小是确定不变的,不能随意的向数组中增加元素,丧失了vector的灵活性。
3.5.2 访问数组元素
3.30 指出下面代码中的索引错误。
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
ia[ix] = ix;
ix <= array_size,中数组下标越界
3.31 编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。
3.32 将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序,实现类似的功能。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int arr1[10] = {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9};
int arr2[10];
int i = 0;
for(auto a : arr1)
{
arr2[i] = a;
cout << arr2[i] << " ";
++i;
}
cout << endl;
vector<int> v1 , v2;
for(int i = 0 ; i < 10 ; ++i)
v1.push_back(i);
v2 = v1;
for(auto i : v2)
cout << i << " ";
cout << endl;
return 0;
}
3.33 对于104页的程序来说,如果不初始化scores将会发生什么?
数组元素的值将不能确定。
3.5.3 指针和数组
3.34 假定p1 和 p2 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?
p1 += p2 - p1;
将p1移动(p2-p1)个位置,当p1或p2位置不合法时,该程序不合法
3.35 编写一段程序,利用指针将数组中的元素置为0。
#include<iostream>
using namespace std;
int main()
{
int arr[3];
for(auto &i : arr)
{
i = 0;
cout << i << " ";
}
cout << endl;
return 0;
}
3.36 编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。
#include<iostream>
#include<vector>
using namespace std;
bool compare_int(int *beg1 , int *end1 , int *beg2 , int *end2)
{
if((end1-beg1) == (end2-beg2))
{
for(int *p1 = beg1 , *p2 = beg2 ; p1 != end1 && p2 != end2 ; ++p1 , ++p2)
{
if(*p1 != *p2)
return false;
}
return true;
}
else
return false;
}
int main()
{
int arr1[10] = {0 , 1 , 2 , 3} , arr2[10] = {0 , 1 , 2};
if(compare_int(begin(arr1) , end(arr1) , begin(arr2) , end(arr2)))
cout << "arr1 = arr2" << endl;
else
cout << "arr1 != arr2" << endl;
vector<int> v1{0 , 1 , 2 , 3};
vector<int> v2{0 , 1 , 2 , 3};
if(v1 == v2)
cout << "v1 = v2" << endl;
else
cout << "v1 != v2" << endl;
return 0;
}
3.5.4 C风格字符串
3.37 下面的程序是何含义,程序的输出结果是什么?
const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp) {
cout << *cp << endl;
++cp;
}
没有遇到\0,循环不会停止,会打印出垃圾信息(存在危险)。
3.38 在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义?
两个指针相加,就相当于两个地址相加所以没有什么意义。
3.39 编写一段程序,比较两个string对象。再编写一段程序,比较两个C风格字符串的内容。
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string s1 = "abcdefg";
string s2 = "acssddd";
if(s1 == s2)
cout << "s1 = s2" << endl;
else
cout << "s1 != s2" << endl;
char ca1[4] = {'a' , 'b' , 'c'} , ca2[5] = {'a' , 'b' , 'c' , 'd'};
if(!strcmp(ca1 , ca2))
cout << "ca1 = ca2" << endl;
else
cout << "ca1 != ca2" << endl;
return 0;
}
3.40 编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用strcpy和strcat把前两个数组的内容拷贝到第三个数组当中。
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
char ca1[] = "hello," , ca2[] = "world";
char ca3[12];
strcat(strcpy(ca3 , ca1) , ca2);
cout << ca3 << endl;
return 0;
}
3.5.5 与旧代码的接口
3.41 编写一段程序,用整型数组初始化一个vector对象。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int arr[] = {1 , 2 , 3 , 4 , 5};
vector<int> v(begin(arr) , end(arr));
for(auto i : v)
cout << i << " ";
cout << endl;
return 0;
}
3.42 编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v(10 , 5);
int arr[10];
for(int i = 0 ; i < 10 ; ++i)
{
arr[i] = v[i];
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
3.6 多维数组
3.43 编写3个不同版本的程序,令其均能输出ia的元素。版本1使用范围for语句管理迭代过程;版本2和版本3都使用普通for语句,其中版本2要求使用下标运算符,版本3要求使用指针。此外,在所有3个版本的程序中都要直接写出数据类型,而不能使用类型别名、auto关键字和decltype关键字。
#include<iostream>
using namespace std;
int main()
{
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
for(const int (&row)[4] : ia)
{
for(int col : row)
cout << col << " ";
cout << endl;
}
cout << endl;
for(size_t i = 0 ; i < 3 ; ++i)
{
for(size_t j = 0 ; j < 4 ; ++j)
cout << ia[i][j] << " ";
cout << endl;
}
cout << endl;
for(int (*p)[4] = begin(ia) ; p != end(ia) ; ++p)
{
for(int *q = begin(*p) ; q != end(*p) ; ++q)
cout << *q << " ";
cout << endl;
}
cout << endl;
return 0;
}
3.44 改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。
#include<iostream>
using namespace std;
using int_array = int[4];
int main()
{
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
for(int_array &row : ia)
{
for(int col : row)
cout << col << " ";
cout << endl;
}
cout << endl;
for(size_t i = 0 ; i < 3 ; ++i)
{
for(size_t j = 0 ; j < 4 ; ++j)
cout << ia[i][j] << " ";
cout << endl;
}
cout << endl;
for(int_array *p = begin(ia) ; p != end(ia) ; ++p)
{
for(int *q = begin(*p) ; q != end(*p) ; ++q)
cout << *q << " ";
cout << endl;
}
cout << endl;
return 0;
}
3.45 再一次改写程序,这次使用auto关键字。
#include<iostream>
using namespace std;
using int_array = int[4];
int main()
{
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
for(auto &row : ia)
{
for(int col : row)
cout << col << " ";
cout << endl;
}
cout << endl;
for(size_t i = 0 ; i < 3 ; ++i)
{
for(size_t j = 0 ; j < 4 ; ++j)
cout << ia[i][j] << " ";
cout << endl;
}
cout << endl;
for(auto *p = begin(ia) ; p != end(ia) ; ++p)
{
for(int *q = begin(*p) ; q != end(*p) ; ++q)
cout << *q << " ";
cout << endl;
}
cout << endl;
return 0;
}
第四章表达式
4.1 基础
4.1.1 基本概念
4.1 表达式 5 + 10 * 20 / 2 的求值结果是多少?
105
4.2 根据4.12节中的表,在下述表达式的合理位置添加括号,使得添加括号后运算对象的组合顺序与添加括号前一致。
(a)(vec.begin());
(b)((vec.begin())) + 1。
4.1.3 求值顺序
4.3 C++语言没有明确规定大多数二元运算符的求值顺序,给编译器优化留下了余地。这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,你认为这可以接受吗?请说出你的理由。
可以接受,效率是C++最大的优势。我们要做的是避免类似代码的产生。
4.2 算术运算符
4.4 在下面的表达式中添加括号,说明其求值过程及最终结果。编写程序编译该(不加括号的)表达式并输出结果验证之前的推断。
(((12/3)4)+(515))+((24%4)/2)
91
4.5 写出下列表达式的求值结果。
-30 * 3 + 21 / 5 // -90+4 = -86
-30 + 3 * 21 / 5 // -30+63/5 = -30+12 = -18
30 / 3 * 21 % 5 // 10*21%5 = 210%5 = 0
-30 / 3 * 21 % 4 // -10*21%4 = -210%4 = -2
4.6 写出一条表达式用于确定一个整数是奇数还是偶数。
i % 2 == 0 ? “even” : “odd”
4.7 溢出是何含义?写出三条将导致溢出的表达式。
short svalue = 32767;
cout << ++svalue << endl; // -32768
unsigned uivalue = 0;
cout << --uivalue << endl; // 4294967295
unsigned short usvalue = 65535;
cout << ++usvalue << endl; // 0
4.3 逻辑和关系运算符
4.8 说明在逻辑与、逻辑或及相等性运算符中运算对象的求值顺序。
逻辑与:当且仅当左侧对象为真时,才对右侧对象求值;
逻辑或:当且仅当左侧对象为假时,才对右侧对象进行求值;
相等运算符:求值顺序不明确。
4.9 解释在下面的if语句中条件部分的判断过程。
const char *cp = "Hello World";
if (cp && *cp)
当且仅当指针cp的地址,不为空时,才对cp的解引用进行判断指向的值。
4. 10 为while 循环写一个条件,使其从标准输入中读取整数,遇到 42 时停止。
while (cin >> i && i != 42)
4.11 书写一条表达式用于测试4个值a、b、c、d的关系,确保a大于b、b大于c、c大于d。
if(a > b && b > c && c > d)
4.12 假设i、j 和k 是三个整数,说明表达式 i != j < k 的含义。
根据4.12运算符优先级表我们得到<的优先级大于!=,所以j < k得到bool值,bool值再与i比较是否不等。等价于:i != (j < k)
4.4 赋值运算符
4.13 在下述语句中,当赋值完成后 i 和 d 的值分别是多少?
int i; double d;
d = i = 3.5; // i = 3, d = 3.0
i = d = 3.5; // d = 3.5, i = 3
4.14 执行下述 if 语句后将发生什么情况?
if (42 = i) // 编译错误。赋值运算符左侧必须是一个可修改的左值。而字面值是右值。
if (i = 42) // true.
4.15 下面的赋值是非法的,为什么?应该如何修改?
double dval; int ival; int *pi;
dval = ival = pi = 0;
pi是指针类型,无法转换为int类型
4.16 尽管下面的语句合法,但它们实际执行的行为可能和预期并不一样,为什么?应该如何修改?
if (p = getPtr() != 0)//(p = getPtr()) != 0
if (i = 1024)//i == 1024
4.5 递增和递减运算符
4.17 说明前置递增运算符和后置递增运算符的区别。
前置递增运算符:先递增,在返回改变后的运算对象
后置递增运算符:先返回原始值,再进行递增操作
4.18 如果132页那个输出vector对象元素的while循环使用前置递增运算符,将得到什么结果?
不会打印vector对象中的第一个元素,如果序列没有负值,程序将可能解引用一个不存在的元素
4.19 假设 ptr 的类型是指向 int 的指针、vec 的类型是vector、ival 的类型是int,说明下面的表达式是何含义?如果有表达式不正确,为什么?应该如何修改?
(a) ptr != 0 && *ptr++
(b) ival++ && ival
(c) vec[ival++] <= vec[ival]
(a)当ptr指针地址不为空时,判断ptr指向的值是否为0;
(b)ival+1不为0时,判断ival是否为0;
(c)vec[ival+1] <= vec[ival]
4.6 成员访问运算符
4.20 假设 iter 的类型是 vector::iterator, 说明下面的表达式是否合法。如果合法,表达式的含义是什么?如果不合法,错在何处?
(a) *iter++;//解引用当前元素,并且指针指向下一个元素
(b) (*iter)++;//不合法,*iter是字符,不能++
(c) *iter.empty();//iter本身是一个指针且不包含任何成员
(d) iter->empty();//运行iter所指对象的empty成员
(e) ++*iter;//不合法,*iter是字符,不能++
(f) iter++->empty();//合法,先判断是否为空,再iter++
4.7 条件运算符
4.21 编写一段程序,使用条件运算符从 vector 中找到哪些元素的值是奇数,然后将这些奇数值翻倍
#include<iostream>
using namespace std;
#include<vector>
int main()
{
vector<int> v{1 , 2 , 3 , 4 , 5};
for(auto &i : v)
{
i = (i % 2 != 0) ? 2*i : i;
cout << i << " ";
}
cout << endl;
return 0;
}
4.22 本节的示例程序将成绩划分为high pass、pass 和 fial 三种,扩展该程序使其进一步将 60 分到 75 分之间的成绩设定为 low pass。要求程序包含两个版本:一个版本只使用条件运算符;另一个版本使用1个或多个if语句。哪个版本的程序更容易理解呢?为什么?
#include<iostream>
using namespace std;
int main()
{
int grade = 0;
cin >> grade;
cout << ((grade >= 90) ? "hogh pass" :
(grade >= 75) ? "pass" :
(grade >= 60) ? "low pass" : "fail") << endl;
if(grade >= 75)
cout << ((grade >= 90) ? "high pass" : "pass") << endl;
else
cout << ((grade >= 60) ? "low pass" : "fail") << endl;
return 0;
}
if语句逻辑更加清晰
4.23 因为运算符的优先级问题,下面这条表达式无法通过编译。根据4.12节中的表指出它的问题在哪里?应该如何修改?
string s = "word";
string pl = s + s[s.size() - 1] == 's' ? "" : "s" ;
+的优先级大于 == 和 ?: 所以会先执行s + (s[s.size() - 1],与程序本意不符,且字符串与字符无法比较。
改为:string pl = s + (s[s.size() - 1] == ‘s’ ? “” : “s”) ;
4.24 本节的示例程序将成绩划分为 high pass、pass、和fail三种,它的依据是条件运算符满足右结合律。假如条件运算符满足的是左结合律,求值的过程将是怎样的?
4.8 位运算符
4.25 如果一台机器上 int 占 32 位、char 占8位,用的是 Latin-1 字符集,其中字符’q’ 的二进制形式是 01110001,那么表达式~‘q’ << 6的值是什么?
0100 0000 ‘@’
4.26 在本节关于测验成绩的例子中,如果使用unsigned int 作为quiz1 的类型会发生什么情况?
int最小为16位,可能会出现位数不够的情况。
4.27 下列表达式的结果是什么?
unsigned long ul1 = 3, ul2 = 7;
(a) ul1 & ul2
(b) ul1 | ul2
(c) ul1 && ul2
(d) ul1 || ul2
011
111
(a)011,3
(b)111,7
(c)true
(d)true
4.9 sizeof运算符
4.28 编写一段程序,输出每一种内置类型所占空间的大小。
#include <iostream> // high level input/output operations.
using namespace std;
int main()
{
// void type
cout << "void: nullptr_t\t" << sizeof(std::nullptr_t) << " bytes" << endl << endl;
// boolean type
cout << "bool:\t\t" << sizeof(bool) << " bytes" << endl << endl;
// charactor type
cout << "char:\t\t" << sizeof(char) << " bytes" << endl;
cout << "wchar_t:\t" << sizeof(wchar_t) << " bytes" << endl;
cout << "char16_t:\t" << sizeof(char16_t) << " bytes" << endl;
cout << "char32_t:\t" << sizeof(char32_t) << " bytes" << endl << endl;
// integers type
cout << "short:\t\t" << sizeof(short) << " bytes" << endl;
cout << "int:\t\t" << sizeof(int) << " bytes" << endl;
cout << "long:\t\t" << sizeof(long) << " bytes" << endl;
cout << "long long:\t" << sizeof(long long) << " bytes" << endl << endl;
// floating point type
cout << "float:\t\t" << sizeof(float) << " bytes" << endl;
cout << "double:\t\t" << sizeof(double) << " bytes" << endl;
cout << "long double:\t" << sizeof(long double) << " bytes" << endl << endl;
// Fixed width integers
cout << "int8_t:\t\t" << sizeof(int8_t) << " bytes" << endl;
cout << "uint8_t:\t" << sizeof(uint8_t) << " bytes" << endl;
cout << "int16_t:\t" << sizeof(int16_t) << " bytes" << endl;
cout << "uint16_t:\t" << sizeof(uint16_t) << " bytes" << endl;
cout << "int32_t:\t" << sizeof(int32_t) << " bytes" << endl;
cout << "uint32_t:\t" << sizeof(uint32_t) << " bytes" << endl;
cout << "int64_t:\t" << sizeof(int64_t) << " bytes" << endl;
cout << "uint64_t:\t" << sizeof(uint64_t) << " bytes" << endl;
return 0;
}
4.29 推断下面代码的输出结果并说明理由。实际运行这段程序,结果和你想象的一样吗?如不一样,为什么?
int x[10]; int *p = x;
cout << sizeof(x)/sizeof(*x) << endl;//10
cout << sizeof(p)/sizeof(*p) << endl;//1
4.30 根据4.12节中的表,在下述表达式的适当位置加上括号,使得加上括号之后的表达式的含义与原来的含义相同。
(a) sizeof x + y// (sizeof x) + y
(b) sizeof p->mem[i] //sizeof (p->mem[i])
(c) sizeof a < b //(sizeof a) < b
(d) sizeof f() //sizeof (f())
4.10 逗号运算符
4.31 本节的程序使用了前置版本的递增运算符和递减运算符,解释为什么要用前置版本而不用后置版本。要想使用后置版本的递增递减运算符需要做哪些改动?使用后置版本重写本节的程序。
后置版本需要将未修改的值保存下来,以便返回,如果不需要未修改的值就使用前置版本。使用后置版本无需改动。
4.32 解释下面这个循环的含义。
constexpr int size = 5;
int ia[size] = { 1, 2, 3, 4, 5 };
for (int *ptr = ia, ix = 0;
ix != size && ptr != ia+size;
++ix, ++ptr) { /* ... */ }
ptr和ix的功能都是为了遍历数组,功能一样,实现的过程不一样,ptr是指针方式实现,ix是索引方式实现
4.33 根据4.12节中的表说明下面这条表达式的含义。
someValue ? ++x, ++y : --x, --y//(someValue ? ++x, ++y : --x), --y
4.11 类型转换
4.11.1 算术转换
4.11.2 其他隐式类型转换
4.11.3 显示转换
4.36 假设 i 是int类型,d 是double类型,书写表达式 i*=d 使其执行整数类型的乘法而非浮点类型的乘法。
i *= static_cast<int>(d);
4.37 用命名的强制类型转换改写下列旧式的转换语句。
#include<iostream>
using namespace std;
int main()
{
int i; double d; const string *ps; char *pc; void *pv;
//pv = (void*)ps;
pv = static_cast<void*>(const_cast<string *>(ps));
//i = int(*pc);
i = static_cast<int>(*pc);
//pv = &d;
pv = static_cast<void*>(&d);
//pc = (char*)pv;
pc = static_cast<char*>(pv);
return 0;
}
4.38 说明下面这条表达式的含义。
double slope = static_cast<double>(j/i);
将(j/i)转换为double,并赋值给slope。
4.12 运算符优先级表