[C++ Primer notes] Chapter 2 练习题 变量和基本类型

Chapter 2 练习题

环境: CLion + MinGW

2.1 类型int、long、long long和short的区别是什么?无符号类型和带符号类型的区别是什么?float和double的区别是什么?

(1) int、long、long long和short都是整型,在C++中规定,int至少和short一样大,long至少和int一样大,long long至少和long一样大

在Win64电脑上,环境为CLion+MinGW64+GCC8.1.0运行以下程序

cout<<"Size of short is "<<sizeof(short)<<" bytes."<<endl;
cout<<"Size of int is "<<sizeof(int)<<" bytes."<<endl;
cout<<"Size of long is "<<sizeof(long)<<" bytes."<<endl;
cout<<"Size of long long is "<<sizeof(long long)<<" bytes."<<endl;

结果为

Size of short is 2 bytes.
Size of int is 4 bytes.
Size of long is 4 bytes.
Size of long long is 8 bytes.

(2) 无符号类型只能表示非负数,没有符号位;有符号类型可以表示正数、负数和零,最高位为符号位

(3) float为单精度浮点数,double为双精度浮点数

在Win64电脑上,环境为CLion+MinGW64+GCC8.1.0运行以下程序

cout<<"Size of float is "<<sizeof(float)<<" bytes."<<endl;
cout<<"Size of double is "<<sizeof(double)<<" bytes."<<endl;
cout<<"Size of long double is "<<sizeof(long double)<<" bytes."<<endl;

结果为

Size of float is 4 bytes.
Size of double is 8 bytes.
Size of long double is 16 bytes.

2.2 计算按揭贷款时,对于利率、本金和付款分别应选择何种数据类型?说明你的理由

一般情况下均选择double,double精度比float高且计算代价相当,而long double精度更高但计算代价较大

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
// 补充
std::cout << u - i2 << std::endl;	// 2^32 - 32, 混用带符号数和无符号数, 带符号数转换为无符号数

2.4 同上

2.5 指出下述字面值的数据类型并说明每一组内几种字面值的区别

'a', L'a', "a", L"a"	// 字符a;宽字符型字面值a,类型为wchar_t;字符串a,宽字符型字符串a

10, 10u, 10L, 10uL, 012, 0xC	// int;unsigned int; long; unsigned long; 八进制数(10);十六进制数(12)

3.14, 3.14f, 3.14L	// double; float; long

10, 10u, 10., 10e-2	// int; unsigned; double; double(0.1)

2.6 下面两组定义是否有区别

int month = 9, day = 7;
int month = 09, day = 07;	// 八进制数, 且09会引起编译器报错, 应为011

2.7 下述字面值表示何种含义?它们各自的数据类型是什么?

"Who goes with F\145rgus?\012"		// 转义字符,\145表示字符e,\012为换行符
3.14e1L		// long double型(31.4)
1024f		// float型(1024.0)
3.14L		// long double型(3.14)

2.8 用转义字符输出2M并换行,然后修改程序让其输出2,再输出制表符,再输出M并换行

int main(){
	std::cout << "2\x4d\012";
	std::cout << "2\t\x4d\012";
	return 0;
}

2.9 解释下列定义的含义,并改正非法定义

std::cin >> int input_value;	// input_value应提前定义
int i = {3.14};					// i被赋值为3
double salary = wage = 9999.99;	// wage未提前定义, 报错
int i = 3.14;					// i被赋值为3

对于第三行,若wage提前定义,则正确

double wage;
double salary = wage = 9999.99;	// 该语句定义变量salary,给wage赋值,并对salary初始化

2.10 下列变量的初值分别是什么?

std::string global_str;	// string类默认初始化为空字符串
int global_int;			// 函数体外定义int型, 默认初始化为0
int main(){
	int local_int;			// 函数体内定义基础类型, 未初始化则值为未定义
	std::string local_str;	// string类默认初始化为空字符串
}

2.11 指出下面的语句是声明还是定义

extern int ix = 1024;	// 定义, 给extern标记的变量赋值将抵消extern的作用, 变为定义语句
int iy;					// 定义和声明
extern int iz;			// 声明

2.12 指出下面的名字哪个是非法的?

int double = 3.14;	// 非法, double为C++保留的关键字
int _;				// 在函数体内时非法, 函数体内名字不能以_开头
int catch-22;		// 非法, -不是有效名字
int 1_or_2 = 1;		// 非法, 不能以数字开头
double Double = 3.14;	// 合法但不好, 变量名一般均为小写字母, 自定义类名以大写字母开头

2.13 下面程序中j的值是多少?

int i = 42;
int main(){
	int i = 100;	// 内层作用域的i覆盖了外层作用域的i
	int j = i;		// j的值为100
}

2.14 下面程序合法吗?若合法,将输出什么?

int i = 100, sum = 0;
for(int i = 0; i != 10; ++i)
	sum += i;
std::cout << i << " " << sum << std:endl;	// 输出100 45

2.15 下面的定义哪个是非法的?为什么?

int ival = 1.01;
int &rval1 = 1.01;	// 非法, 引用不能绑定字面值常量
int &rval2 = ival;
int &rval3;			// 非法, 引用必须初始化

2.16 哪些赋值是非法的?为什么?

int i = 0, &r1 = i;
double d = 0, &r2 = d;
r2 = 3.14159;	// 将3.14159赋给d
r2 = r1;		// 将0.0赋给d
i = r2;			// 将0赋给i
r1 = d;			// 将0赋给i
// 均为合法的

2.17 执行下面的代码段将输出什么结果?

int i, &ri = i;
i = 5;
ri = 10;
std::cout << i << " " << ri << std::endl;	// 10 10

2.18 编写代码分别更改指针的值及指针所指对象的值

int a = 1, *pa = &a;	
*pa = 2;		// 改变pa所指对象a的值为2
pa = nullptr;	// 改变pa的值为空指针

2.19 说明指针和引用的主要区别

(1) 引用必须初始化,且此后将始终绑定该对象;指针可以不初始化,其值能够改变

(2) 引用本身不是对象,指针本身就是对象

2.20 叙述下面代码的作用

int i = 42;
int *pi = &i;		// 指针pi指向变量i
*pi = *pi * *pi;	// 取变量i与变量i相乘, 结果存入变量i, 故i的终值为42*42

2.21 解释下属定义,判断是否非法

int i = 0;
double *dp = &i;	// 非法, dp为指向double对象的指针, 但初始化指向了int变量
int *ip = i;		// 非法, ip为指针, 不能直接用int变量赋值, 只能用int变量的地址赋值
int *p = &i;		// 合法

2.22 假设p是一个int型指针,说明下述代码的含义

if(p){}		// 若p不是空指针, 执行块中语句
if(*p){}	// 若p指向对象不为0, 执行块中语句

2.23 给定指针p,你能知道它是否指向了一个合法的对象吗?

把p作为if语句条件,若为空指针则条件为假,反之为真

2.24 为什么p合法而lp非法

int i = 42;
void *p = &i;	// void*指针可以指向任意类型的对象	
long *lp = &i;	// long指针不能指向int变量

2.25 说明下列变量的类型和值

int *ip, i, &r = i;	// ip为int指针, i为int变量, r为绑定i的引用
int i, *ip = 0;		// i为int变量, ip为int指针,当前值为空
int *ip, ip2;		// ip为int指针, ip2为int变量

2.26 判断是否合法

const int buf;		// 非法,const对象必须初始化
int cnt = 0;
const int sz = cnt;	// 合法,const int对象可用int变量初始化
++cnt;				
++sz;				// 非法,const int变量的值不可改变

2.27 判断初始化是否合法

int i = -1, &r = 0;			// 非法,引用不能绑定字面值常量
int *const p2 = &i2;		// 合法,p2是一个常量指针(顶层const)
const int i = -1, &r = 0;	// 合法,常量引用可以绑定字面值常量
const int *const p3 = &i2;  // 合法,p3是一个指向常量对象的常量指针
const int *p1 = &i2;		// 合法
const int &const r2;		// 非法,引用必须初始化,且引用不是对象,不能指定顶层const
const int i2 = i, &r = i;  	// 合法

2.28 说明下面的定义是什么意思,挑出其中不合法的

int i, *const cp;		// 非法,常量指针必须初始化
int *p1, *const p2;		// 非法,常量指针必须初始化
const int ic, &r = ic;	// 非法,ic必须初始化
const int *const p3;	// 非法,常量指针必须初始化
const int *p;			// 合法,指针p指向int常量

2.29 假设已有2.28定义的变量,下面的语句哪些是合法的

i = ic;		// 合法
p1 = p3;	// 非法,常量指针不可指向常量对象
p1 = &ic;	// 非法,普通指针不能指向常量对象
p3 = &ic;	// 非法,常量指针的值不可变
p2 = p1;	// 非法,常量指针的值不可变
ic = *p3; 	// 非法,const int的值不可变

2.30 判断对象被声明为顶层const还是底层const

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,r2是底层const

2.31 在2.30的基础上,判断下面的语句合法,说明顶层const或底层const的体现

r1 = v2;	// 合法,赋值语句,相当于将v2的值赋给v1
// 若为定义语句const int &r1 = v2; 则不合法,因为非const引用不可指向常量对象
p1 = p2;	// 不合法,p2为底层const
p2 = p1;	// 合法
p1 = p3;	// 不合法,p3底层const
p3 = p1;	// 不合法,p3顶层const
p2 = p3;	// 合法,p2和p3均为底层const

2.32 下面的代码是否合法?如果非法,请将其修改正确

int null = 0, *p = null;	// 非法
// 若想让p指向null,应该为int null = 0, *p = &null;
// 若想初始化为空指针,应该为int null = 0, *p = nullptr;

2.33 判断运行结果

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;		// 合法,a为int
b = 42;		// 合法,auto忽略顶层const,b为int
c = 42;		// 合法,auto忽略顶层const,c为int
d = 42;		// 非法,d为int*
e = 42;		// 非法,e为const int*,指向int常量的指针
g = 42;		// 非法,g为绑定const int的引用

2.34 同上

2.35 判断下列定义推断出的类型是什么,编写程序进行验证

const int i = 42;		// const int
auto j = i;				// int
const auto &k = i;		// 指向const int的引用
auto *p = &i;			// 指向const int的指针
const auto j2 = i, &k2 = i;	// j2为const int, k2为指向const int的引用

2.36 指出下列代码每个变量的类型,及程序结束时它们各自的值

int a = 3, b = 4;	// a, b为int
decltype(a) c = a;	// c为int
decltype((b)) d = a;// d为指向int的引用
++c;	
++d;	// 程序结束时,a, b, c, d均为4

2.37 赋值是会产生引用的表达式,引用的类型为左值的类型

int a = 3, b = 4;	// a, b为int
decltype(a) c = a;	// c为指向int的引用
decltype(a = b) d = a;	// d为指向int的引用,其中decltype只返回赋值表达式的类型,不会执行a = b
// a, c, d为3, b为4

2.38 说明由decltype指定类型和由auto指定类型有何区别

const int a = 1;
auto b = a;			// b为int型
decltype(a) c = 1; 	// c为const int型

2.39 编译程序并运行,查看相关信息

struct Foo {}	// 没有分号, 无法编译通过
int main(){
	return 0;
}
发布了27 篇原创文章 · 获赞 0 · 访问量 388

猜你喜欢

转载自blog.csdn.net/young_cr7/article/details/105127221