c++ primer习题——第2章 变量和基本类型

参考书目:c++ primer第五版,c++ primer习题集

练习2.1

int、long、long long 和short的不同点在于在内存中尺寸不同,即表示的整数的范围不同。c++标准规定每种尺寸的最小值:short占16位,int占16位,long为32位,long long为64位。

无符号类型只能表示0和正数,32位的无符号类型整数能表示 [ 0 , 2 32 − 1 ] [0, 2^{32}-1] [0,2321]的范围,而32为带符号整数能表示 [ − 2 31 , 2 31 − 1 ] [-2^{31} , 2^{31}-1] [231,2311]的范围

float和double的区别在于在内存中的长度不同,主要体现在double能表示的精度比float高,且表示的最大最小数大于float

练习 2.2

首先要采用浮点数表示,我会用double

练习2.3

第一个cout语句,执行结果正确,42-10=32
第二个cout语句,10-42=-32,而由于两个数都是无符号整数,发生溢出,结果为 − 32 + 2 32 = 4294967264 -32+2^{32}=4294967264 32+232=4294967264 (我的int占32位,这也说明了练习2.1中,c++规定了int最少占16位,但是没有规定一定是16位)

第三个cout,两个有符号整数运算,结果是有符号的,为32
第四个cout,同理,10-42=-32,没有问题
第五个cout,有符号数与无符号数做运算,编译器先把有符号数转化为无符号整数,10还是10,10-10=0,没有溢出
第六个cout 同理

练习 2.5

考察的是这个表,注意对于字符和字符串是前缀,对于浮点数和整数是后缀
在这里插入图片描述

(a)第一个是字符a。第二个是宽字符型字面值 a, 第三个是字符串a,第四个是宽字符型字符串a
(b)10是整数字面值,10u是无符号数,10L是长整型,10uL是无符号长整数,012是八进制12,其十进制是10,0xC是十六进制数,十进制是12

注意后缀指出的是最小匹配类型,由于这里的数比较小,不用考虑容纳不下的情况
(c ) 3.14默认使用double存储,3.14f是float, 3.14L是long double
(d) 10是整数,10u是无符号整数,10. 是浮点数,10e-2是浮点数0.1

练习2.6

第一行是10进制的int
第二行是八进制的int,其中month=09会报错

练习2.7

(a)???真的有人这样表示吗?转义字符“\”后面可以加三位八进制的ASCII码,注意是八进制,\145是e \120是换行符
(b)long double的31.4,
(c)1024的float
(d)long double的3.14

练习2.8

#include<iostream>
using namespace std;
int main(){
	cout<<"2M\n";
	cout<<"2\tM\n";
	return 0;
}

练习2.9

使用dev c++编译
(a)[Error] expected primary-expression before ‘int’
正确做法,先定义变量,再cin

int input_value;
std::cin>>input_value;

(b)得到整型 i=3
(c)[Error] ‘wage’ was not declared in this scope
正确做法,先定义,再赋值

double salary,wage;
salary=wage=999.99;

(d)得到整型 i=3

练习2.10

这三句话:

  • 定义于任何函数体之外的变量被初始化为0
  • 定义在函数体内部的内置类型变量将不被初始化
  • 类的对象如果没有显式地初始化,则其值由类确定。

所以,global_str和local_str为空字符串,global_int=0,local_int 未定义。

练习2.11

(a)定义变量 ix,注意不能放在函数内部,否则报错
(b)声明并定义iy
©声明iy但不定义

练习2.12

不能用关键字为名称,只能包含下划线、数字、字母,不能以数字开头
正确:(b) (e) ,其他错误

练习2.13

j=100,局部变量覆盖全局变量

练习2.14

输出100和45,注意循环内的i和循环外的i是不一样的

练习2.15

(a)合法,得到ival=1
(b)不合法,引用不能绑定字面值,改为const & rval1=1.01可以
(c)合法
(d)不合法,引用必须初始化

练习2.16

(a)合法,相当于把变量d的值变为3.14159
(b)合法,相当于把 i 赋值给d
(c)合法,相当于把 d 赋值给 i
(d)合法,同(c)

练习2.17

都输出10,分析过程可以直接把 ri 换成 i 来看

练习2.18

int main(){
	int i=1,j=2;
	int* p=&i;
	p=&j //改变指针本身的值
	*p=100//改变指针所指对象(j)的值
	return 0;
}

练习2.19

指针本身是内存中的对象,而引用不是对象
指针可以指向不同的其他对象,而引用一经绑定不能再改变所绑定的对象
指针可以在定义时不初始化,但是引用必须在定义时初始化

练习2.20

计算42的平方

练习2.21

(a)不合法,指针的类型必须和变量的类型匹配。
(b)非法,不能直接把int赋值给int*
(c)合法

练习2.22

检测指针p是否为空指针
检测p指向的int是否为0

练习2.23

在某些情况下,我们能知道指针没有执行一个合法的对象,比如指针为0,指针指向了禁止访问的区域,程序报错。但是反过来并不能说明指针指向的合法的内存。例如在dev c++编译运行下面的代码:

int main(){
	int i=0;
	int* pi=&i;
	cout<<*(p+10);
	return 0;}

并没有报错,但是输出了未定义的值

练习2.24

p合法是因为void* 指针可以指向任意类型的变量,而long* 的指针只能指向long型的变量

练习2.25

(a)ip是int 型指针,i是int型变量,r 是 int型的引用,且绑定了变量i
(b)i是int 型变量,ip是int型指针且被初始化为0
(c)ip是int型指针,ip2是int型变量

练习2.26

(a)非法,const变量和引用类似,必须初始化
(b)合法
(c)合法
(d)非法,对于cnt可以自增,但是sz是const变量,不能自增

练习2.27

(a)非法,引用 r 必须绑定对象而不是绑定字面值
(b)合法
(c)合法,const引用可以绑定字面值
(d)合法
(e)合法
(f)非法,引用本身就不能改变绑定的对象,没有所谓 int &const r2(答案是:引用本身不是对象,不能让引用恒定不变)
(g)合法

练习2.28

(a)定义一个int型变量和一个指向int的常量指针,非法,cp没有初始化
(b)定义一个指向int的指针p1和指向int的常量指针p2,非法,p2没有初始化
(c)定义int常量ic和const引用r,非法,ic没有初始化
(d)定义一个指向int常量的常量指针,非法,p3没有初始化
(e)定义了一个指向int常量的指针,合法,他可以不初始化。同时,const决定我们不能通过p3改变其指向的值,但是不要求 p 必须指向const int类型的变量。

练习2.29

(a)合法 i 是int,可以改变值
(b)合法,p1和p3都指向int,且p1不是常量指针
p1是普通指针,而p3是指向常量的指针,如果合法,那么可以通过p1更改p3指向内容,逻辑说不过去
(c)不合法,ic是个常量,p1是普通指针
(d)合法,ic是常量,p3是指向常量的指针,相匹配
非法,常量指针不能赋值
(e)非法,常量指针不能赋值
(f)非法,常量不能被赋值

总结:这个题错的有点离谱,总结一下:

  1. 要考虑赋值运算符左边的对象的顶层const,即本身能不能赋值
  2. 考虑底层的const,有const可以指向没const的,没const不能指向const
  3. 要考虑类型匹配(这里没有这个问题)

练习2.30

v2是顶层const
p2是底层const
p3是顶层const和底层const
r2是底层cosnt

练习2.31

第一个语句是合法的,首先r1没有底层const,所以可以直接赋值,v2是被拷贝的对象,他虽然自身有顶层const但是不受影响。最终结果将改变变量v1的值。

第二行第一个是非法,p2有底层const,p1没有,p1在左,p2在右,非法操作;

第二行第二个,反过来是可以的,首先考虑p2没有顶层const,可以赋值。其次p2有底层const,p1没有,p2在左边,没问题

第三个第一个,非法,左边没有底层const,右边有底层const,非法

第三行第二个,合法,首先p2没有顶层const,可以赋值。左右两边都有底层const,没有问题。类型匹配

练习2.32

空指针应该被初始化为nullptr,而不是整型数字0,这两者是有区别的。

练习2.33

a的值变为42
b的值变为42
c的值变为42
d报错,d是个指针,不能直接用整数赋值
e是个指向常量的指针,不能用整数赋值
g绑定了ci,ci是个常量,不能赋值

练习2.34

练习2.35

j是一个普通的int变量,因为auto不会保留顶层const
k会是一个与int变量绑定的const引用
p是指向整型常量的指针,因为auto会保留底层const
j2是个整数常量,因为定义的时候显示指明了const,k2是整数常量引用 (习题册可能想说auto 推出的是int?)

实验1:改变 j 的值,不影响 i 和 k 的值——证明 j 是一个独立的int变量
实验2:对i,k,k2 取地址,两者地址相同;对i k赋值,编译报错

参考书代码关键点:typeid().name(),用于获得表达式的类型,以c-style字符串形式返回类型名。
搞不懂对于const int i=42,为什么调用上面的函数输出的是int?

练习2.36

a是一个整型
b是一个整型
c是一个整型
d是一个引用且绑定了a

结束后
a=4,b=4,c=4,d=4

练习 2.37

a是int,b是int,c是int,d是int的引用
a,b,c,d 3,4,3,4
因为第三行 a=b 并不会被真正执行

练习2.38

  1. 对于引用,auto使用的是引用绑定的对象“本尊”,decltype会保留引用类型
  2. 对于const,auto会忽略顶层const保留底层const,而decltype会同时保留顶层const和底层const
  3. 对于括号,decltype给变量名加上一对括号会得到引用类型,不加括号是该变量的类型

推断出来的结果一样:

int main(){
	int i=42;
	auto ai=i;
	decltype(i) bi=i;
}

上述代码推断的ai和bi都是int

推断出来结果不同:

int main(){
	const int i=42;
	auto ai=i;
	decltype(i) bi=i;
}

对于ai,由于auto忽略顶层const,其类型是int;而decltype会保留顶层const,类型是const int

练习2.39

报错信息:[Error] expected ‘;’ after struct definition

练习2.40

后面的编程题应该自己发挥就好了

总结

判断表达式正确和错误

  1. 要考虑赋值运算符左边的对象的顶层const,即本身能不能赋值
  2. 考虑底层的const,有const可以指向没const的,没const不能指向const
  3. 要考虑类型匹配(这里没有这个问题)

auto与decltype

  1. 对于引用,auto使用的是引用绑定的对象“本尊”,decltype会保留引用类型
  2. 对于const,auto会忽略顶层const保留底层const,而decltype会同时保留顶层const和底层const
  3. 对于括号,decltype给变量名加上一对括号会得到引用类型,不加括号是该变量的类型
  4. decltype只判断表达式的类型,不会执行表达式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值