C++ Prime 第四章 表达式
2023-03-16~2023-03-17
左值和右值
- 左值=地址(指针)
- 右值=地址的内容(指针指向的内容)
4.1.2 节练习
- 练习 4.1:105
- 练习 4.2:
(a)* (vec.begin())
(b)* (vec.begin()) + 1\
4.2 节练习
- 练习 4.4:
((12 / 3) * 4) + (5 * 15) + ((24 % 4) / 2) - 练习 4.5:
(a)-86
(b)-18
(c)10
(d)-10\
短路求值
- 当且仅当左侧的对象无法确定表达式结果时,才会计算右侧对象(例子:逻辑与运算符-左侧为真、逻辑或运算符-左侧为假)
4.3节练习
- 练习 4.8:逻辑与、逻辑或是短路求值,相等性运算符先判断等号右边的数据类型是否与等号左边的相同,不同就将右边的数据类型转化成左边的再进行判断
- 练习 4.9:先判断cp是否为空指针,为空指针直接返回false,不为空指针就判断* cp是否为空字符串,为空直接返回false,不为空返回true
- 练习 4.10:
using namespace std;
#include<iostream>
int main()
{
int temp;
while (cin >> temp)
{
if (temp == 42)
{
break;
}
}
system("pause");
return 0;
}
- 练习 4.12:判断i不等于0或者不等于1
复合运算符
- 符合运算符相比于怕普通运算符,符合运算符只求值一次,普通运算符求值两次(一次计算右边整体,一次将右边整体赋值给左边)
4.4 节练习
- 练习 4.13:
(a)d=3, i=3
(b)d=3.5, i=3 - 练习 4.14:
if (42 = i) 非法
if (i = 42) 如果i等于42执行if后续语句不等于执行else语句 - 练习4.15:
dval = ival = 0
pi = 0 - 练习 4.16:
(a)if ((p = getPtr()) != 0)
(b)if (i) 或者 if (i == 1024) 两种不同的意思,感觉按照题目来应是if(i)
递增和递减运算符
- 如果不是需要使用到递增或者递减之前的数值,就使用前置递增、递减可以节省性能(后置递增、递减会将递增、递减之前的数值的副本作为返回值返回)
4.5 节练习
- 练习 4.17:后置递增、递减会将递增、递减之前的数值的副本作为返回值返回,前置递增、递减会直接将数值返回
- 练习 4.18:少输出一个正数,多输出一个负数(如果负数存在vector中,并且负数前存在正数)
- 练习4.19:
(a)判断ptr不是空指针并且ptr指向的值不是0,可以修改为:ptr && * ptr
(b)判断ival是否等于0并且ival加1后是否等于0,可以修改为:ival && ++ival
(c)判断vec的ival下标的值是否小于等于vec的ival+1下标的值,可以修改为:vec[ival] <= vec[++ival]
4.6 节练习
- 练习 4.20:
(a):合法,返回iter这个迭代器当前位置指向的数据 (b):不合法,修改为:* iter++ (c):不合法,修改为:* (iter).empty() (d):合法,返回这iter这个迭代器当前位置指向的数据 (e):不合法,修改为:* ++iter (f):合法,判断iter这个迭代器当前位置指向的数据是否是空字串,为空返回1,不为空返回0
4.7 节练习
- 练习 4.21:
using namespace std;
#include<iostream>
#include<vector>
int main()
{
vector<int> vec = { 1, 2, 3, 4, 5, 6};
for (decltype(vec.size()) i = 0; i < vec.size(); i++)
{
int ret = (vec[i] % 2 != 0) ? vec[i] * 2 : 0;
if (ret != 0)
{
cout << ret << endl;
}
}
system("pause");
return 0;
}
- 练习 4.22:多个if更好理解,结构清晰
using namespace std;
#include<iostream>
#include<vector>
int main()
{
int score = 91;
cout << ((score > 90) ? "high"
: (score > 60 && score < 75) ? "low pass"
: score > 60 ? "pass" : "fail");
system("pause");
return 0;
}
- 练习 4.23: string p1 = s + (s[s.size() - 1] == 's' ? "" : "s");
- 练习 4.24:相当于把只会进入>60或者<60的流程,所有只有fail和pass这两个结果
4.8 节练习
- 练习4.25:
q = 00000000 00000000 00000000 011100001
~q = 11111111 11111111 11111111 100011110
~q<<6 = 11111111 11111111 111000111 10000000\ - 练习4.26: 在16为的编译器上工作时,只能确保占用16位,不够用
- 4.27:
unsigned long ul1 = 3, ul2 = 7;
ul1 = 00000000 00000000 00000000 00000011
ul2 = 00000000 00000000 00000000 00000111
(a):00000000 00000000 00000000 00000011
(b):00000000 00000000 00000000 00000111
(c):1
(d):1
sizeof运算符
- 对解引用指针执行sizeof运算得到指针指向的对象所占空间的大小,指针不需要有效,因为sizeof不需要真的解引用就可以知道它所指对象的大小
4.9 节练习
- 练习 4.28:
using namespace std;
#include<iostream>
#include<vector>
int main()
{
cout << sizeof(int) << endl;
cout << sizeof(unsigned int) << endl;
cout << sizeof(long) << endl;
cout << sizeof(unsigned long) << endl;
cout << sizeof(short) << endl;
cout << sizeof(unsigned short) << endl;
cout << sizeof(double) << endl;
// ..........
system("pause");
return 0;
}
- 练习 4.29:
10,2或者1 使用64位编译器,一个指针大小=8字节,使用32位编译器,一个指针大小是4字节 - 练习 4.30:
(a)(sizeof x)+y
(b)sizeof(p->mem[i])
(c)(sizeof a) < b
(d)sizeof (f())
4.10 节练习
- 练习 4.31: 程序设计时没有后置递增、递减的需求,实际实现时前置和后置没啥区别
using namespace std;
#include<iostream>
#include<vector>
int main()
{
vector<int> ivec = { 12, 22, 32, 24 };
vector<int>::size_type cnt = ivec.size();
for (vector<int>::size_type ix = 0;
ix != ivec.size();
++ix, --cnt)
ivec[ix] = cnt;
for (auto temp : ivec)
{
cout << temp << endl;
}
system("pause");
return 0;
}
- 练习 4.32:意义:执行5次省略的代码
- 练习 4.33:含义:cout << (someValue ? (++x, ++y) : (--x, --y)) << endl;
不理解在不加括号的情况下,满足someValue的情况下,竟然还会执行--x和-- y的流程。--,++的优先级> ? : 优先级 > ,
###算数转换
- 运算符的运算对象将转换成最宽的类型 ###整型提升
- 对于小整型数据类型char、bool、short等提升成int类型 ###无符号类型的运算对象
- 运算时如果无符号对象类型大于有符号对象,则有符号对象转化成无符号类型,反之亦然
练习4.11.1 节练习
-
练习 4.34:
(a)double->bool
(b)int -> double
(c)char -> int, int -> double -
练习 4.35:
(a)char -> int, int -> char
(b)int -> double, unsigned int -> double, double -> float
(c)unsigned int -> folat, float -> double
(d)int -> float, float -> double, double -> char
显示转换
- static_cast:具有明确意义的类型转化,只要不包含底层const(将常量对象转化成非常量)都可以使用static_cast
using namespace std;
#include<iostream>
int main()
{
double d = 3.14;
void* p = &d;
double* dp = static_cast<double*>(p);
cout << *dp << endl;
system("pause");
return 0;
}
- const_cast:能改变对象的底层const(将常量对象转化成非常量对象),但也只能由于改变底层const
using namespace std;
#include<iostream>
int main()
{
const char a = 'a';
const char* cp = &a;
char* p = const_cast<char*>(cp);
*p = 'b';
cout << *p << endl;
cout << *cp << endl;
cout << a << endl;
system("pause");
return 0;
}
练习 4.11.3
- 练习 4.36:
using namespace std;
#include<iostream>
int main()
{
int i = 10;
double d = 3.14;
//i *= static_cast<int>(d);
cout << i << endl;
system("pause");
return 0;
}
- 练习 4.37: (a):
using namespace std;
#include<iostream>
int main()
{
void *pv;
const string s = "qwer";
const string* ps = &s;
pv = const_cast<string*>(ps);
string* pc = static_cast<string*>(pv);
*pc = "asdf";
cout << *pc << endl;
cout << *ps << endl;
system("pause");
return 0;
}
(b):
using namespace std;
#include<iostream>
int main()
{
int i;
char a = 'a';
char *pc = &a;
i = static_cast<int>(*pc);
cout << i << endl;
system("pause");
return 0;
}
(c):
using namespace std;
#include<iostream>
int main()
{
double d = 3.14;
void *pv;
pv = static_cast<void*>(&d);
double *ps = static_cast<double*>(pv);
cout << *ps << endl;
system("pause");
return 0;
}
(d):pc = reinterpret_cast<char*>(pv)
- 练习4.38:将j/i的值显式强制转化成double类型并赋值给slope
C++Prime学习笔记 文章被收录于专栏
勇敢和愚蠢只有一剑之差