C++primer 第三章、第四章练习题

目录

第三章

3.2 标准库类型string

 3.3 标准库类型

3.3.1 定义和初始化vector对象

 3.3.3 其他vector操作

3.5 数组

3.5.2 访问数组元素

3.5.3 指针和数组

 3.5.4 C风格字符串

 3.5.5 与旧代码的接口

         3.6 多维数组

4.1 基础

4.1.1 基本概念

 4.1.3 求职顺序

 4.2 算术运算符

4.3 逻辑和关系运算符

4.4 赋值运算符

 4.5 递增和递减运算符

4.6 成员访问运算符

 4.7 条件运算符

4.8 位运算符

4.9 sizeof运算符

4.11 类型转换

4.11.1 算术转换

4.11.2 其他隐式类型转换

4.11.3 显示转换


第三章 字符串、向量和数组

3.2 标准库类型string

3.10 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。

#include
#include
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> ivec;
(b)vector svec = ivec;
(c)vector svec(10, "null");

(a) 正确,创建了元素为vector的空vector容器

(b)错误,拷贝构造的元素类型不一样

(c)正确,创建了包含10个元素为null的vector容器

3.13 下列的vector对象各包含多少个元素?这些元素的值分别是多少? 

vector v1;
vector v2(10);
vector v3(10, 42);
vector v4{ 10 };
vector v5{ 10, 42 };
vector v6{ 10 };
vector 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
#include
using namespace std;

int main()
{
    vector vec;
    int i;
    while (cin >> i)
    {
        vec.push_back(i);
    }

    return 0;
}

 3.15 改写上题程序,不过这次读入的是字符串。

#include
#include
using namespace std;

int main()
{
    vector 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 
#include 
#include
using namespace std;

int main()
{
    vector v1;
    cout << v1.empty() << endl;

    vector v2(10);
    cout << v2.size() << endl;
    for(vector::size_type i = 0 ; i < v2.size() ; ++i)
        cout << v2[i] << " ";
    cout << endl;

    vector v3(10, 42);
        cout << v3.size() << endl;
    for(vector::size_type i = 0 ; i < v3.size() ; ++i)
        cout << v3[i] << " ";
    cout << endl;

    vector v4{10};
        cout << v4.size() << endl;
    for(vector::size_type i = 0 ; i < v4.size() ; ++i)
        cout << v4[i] << " ";
    cout << endl;

    vector v5{10, 42};
        cout << v5.size() << endl;
    for(vector::size_type i = 0 ; i < v5.size() ; ++i)
        cout << v5[i] << " ";
    cout << endl;

    vector v6{10};
        cout << v6.size() << endl;
    for(vector::size_type i = 0 ; i < v6.size() ; ++i)
        cout << v6[i] << " ";
    cout << endl;

    vector v7{10, "hi"};
        cout << v7.size() << endl;
    for(vector::size_type i = 0 ; i < v7.size() ; ++i)
        cout << v7[i] << " ";
    cout << endl;

    return 0;
}

 3.17 从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改为大写形式。输出改变后的结果,每个词占一行。

#include
#include
#include
using namespace std;

int main()
{
    vector 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 ivec;
ivec[0] = 42;

 不合法,ivec.push_back(42);

3.19 如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?

vector ivec1(10,42);	//最好,大量重复值,简洁
vector ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector ivec3 = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector ivec4(ivec1);
vector ivec4 = ivec1;

 3.20 读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输入第二个和倒数第二个元素的和,以此类推。

#include
#include
#include
using namespace std;

int main()
{
    vector 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 
#include 
#include
using namespace std;

int main()
{
    vector v1;
    if(v1.begin() == v1.end())
        cout << "v1为空" << endl;

    vector v2(10);
    int i = 0;
    for(auto it = v2.begin() ; it != v2.end() ; ++it)
    {
        cout << *it << " ";
        i++;
    }
    cout << endl;
    cout << "v2的大小为: " << i << endl;
    

    vector v3(10, 42);
    i = 0;
    for(auto it = v3.begin() ; it != v3.end() ; ++it)
    {
        cout << *it << " ";
        i++;
    }
    cout << endl;
    cout << "v3的大小为: " << i << endl;

    vector v4{10};
    i = 0;
    for(auto it = v4.begin() ; it != v4.end() ; ++it)
    {
        cout << *it << " ";
        i++;
    }
    cout << endl;
    cout << "v4的大小为: " << i << endl;

    vector v5{10, 42};
    i = 0;
    for(auto it = v5.begin() ; it != v5.end() ; ++it)
    {
        cout << *it << " ";
        i++;
    }
    cout << endl;
    cout << "v5的大小为: " << i << endl;

    vector v6{10};
    i = 0;
    for(auto it = v6.begin() ; it != v6.end() ; ++it)
    {
        cout << *it << " ";
        i++;
    }
    cout << endl;
    cout << "v6的大小为: " << i << endl;

    vector 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
#include
using namespace std;

int main()
{
    vector 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
#include
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 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
using namespace std;

int main()
{
    int arr[3];
    for(auto &i : arr)
    {
        i = 0;
        cout << i << " ";
    }
    cout << endl;

    return 0;
}

 3.36 编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。

#include
#include
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 v1{0 , 1 , 2 , 3};
    vector 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
#include
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
#include
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
#include
using namespace std;

int main()
{
    int arr[] = {1 , 2 , 3 , 4 , 5};
    vector v(begin(arr) , end(arr));
    for(auto i : v)
        cout << i << " ";
    cout << endl;

    return 0;
}

 3.42 编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组。

#include
#include
using namespace std;

int main()
{
    vector 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
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
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
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
using namespace std;
#include

int main()
{
    vector 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
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  // 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(d);

4.37 用命名的强制类型转换改写下列旧式的转换语句。

#include
using namespace std;

int main()
{
    int i; double d; const string *ps; char *pc; void *pv;
    //pv = (void*)ps;
    pv = static_cast(const_cast(ps));
    //i = int(*pc);
    i = static_cast(*pc);
    //pv = &d;
    pv = static_cast(&d);
    //pc = (char*)pv;
    pc = static_cast(pv);

    return 0;
}

 4.38 说明下面这条表达式的含义。

double slope = static_cast(j/i);

 将(j/i)转换为double,并赋值给slope。

4.12 运算符优先级表

你可能感兴趣的:(c++,算法,数据结构)