2019.04.27第二遍
特别注意的地方
- 与其他整型不同,字符型被分成了三种:char、unsigned char、signed char。char是哪种是由编译器决定的。
- 当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的。此时,程序可能继续工作、可能崩溃、也可能产生垃圾数据。
- 类型short没有对应的字面值。
- 十进制字面值不可能是负值,如有有个带负号的字面值,那么那个负号作用仅仅是对字面值取负值。
- 字符串字面值的实际长度要比它的内容多1 。
- 对象是指一块能存储数据并具有某种类型的内存空间。
- 初始化和赋值是两个完全不同的操作。
- 定义于任何函数体之外的变量被初始化为0,定于在函数体内部的内置类型变量将不被初始化。
- 用花括号来初始化变量被称为列表初始化,这种初始化有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器会报错。
- 如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量。任何包含了显示初始化的声明即成为定义。
- 在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误。
- 用户自定义的标识符中不能连续出现两个下划线,也不能以下划线紧连大写字母开头。定义在函数体外的标识符不能以下划线开头。
- 右值引用主要用于内置类。引用必须被初始化。引用类型的初始值必须是一个对象。
- 指针是对象且无须在定义时赋值。不能定义指向引用的指针。
- 使用未经初始化的指针是引发运行时错误的一大原因。
- 如果利用一个对象去初始化另外一个对象,则它们是不是const都无关紧要。
- auto定义的变量必须有初始值;会忽略掉顶层const。
- 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;
}
运行结果如下
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
100
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
10 10
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
把i乘以2
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
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
2.40
struct Sales_data
{
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// 书上把想的写出来了,“最好”两字说明可以和书上一样~