C++ Primer 学习笔记_16_表达式 -算术、关系、逻辑、位、赋值、自增/自减操作符
表达式
--算术、关系、逻辑、位、赋值、自增/自减操作符
引:
除了特殊用法,表达式的结果为右值:可以读取结果值,但是不能对其进行赋值。
高优先级的操作符要比低优先级的结合得更紧密。
正文:
1、某些算术表达式的求解结果未定义:一部分有数学特性决定,如除0操作;另一部分则归咎于计算机特性,如溢出。
2、除法和求模操作:
1)如果两个操作数都是负数:则除法操作的结果为正数,而求模操作结果为负数
2)如果只有一个操作数是负数:这两种操作的结果都要取决于机器:求模结果的符号要取决于机器,除法操作的值则是负数。
cout << -21 % -8 << endl; cout << 21 % -5 << endl; //1 or -4 cout << -21 / -8 << endl; cout << 21 / -5 << endl; //-4 or -5
3、关系操作符和逻辑操作符的返回结果都是bool类型的值
短路求值-逻辑与&&与逻辑或||,都是只有仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数。
4、一个&&操作符的使用技巧:如果某边界条件使得expr2的计算变得非常危险,那么应该在该条件出现之前,先让expr1成为false。
string s("Expressions in C++ are composed..."); string::iterator iter = s.begin(); while (iter != s.end() && ! isspace(*iter)) { *iter = toupper(*iter); ++ iter; } cout << s << endl;
5、如果逻辑非的操作数为非零值,则!操作的结果为false。
6、不应该串接使用关系操作符,如:
if (i < j < k) { //... }
该表达式的结果往往是出人意料的:这种写法只要k值大于1,则该表达式的结果就为true;
//P133 习题5.7 int main() { int val; while (cin >> val && val != 42) { //... } }
//习题 5.8 if (a > b && b > c && c > d) {//...}
7、位操作符可以将整型操作符视为二进制位的集合,而且还可以作用于bitset类型。
8、如果位操作符的操作数为负数,则位操作符如何处理其操作数的符号要依赖于机器。因此,强烈建议使用unsigned整型操作数。
1<< n :相当于1* 2^n
m<< n :相当于m* 2^n
9、bitset对象与整型值的使用对比
//bitset对象的每一位都默认为0 bitset<30> bitset_quizl; unsigned long int_quizl = 0; //设置第27位为1 bitset_quizl.set(27); int_quizl |= 1UL << 27; //设置第27位为0 bitset_quizl.reset(27); int_quizl &= ~(1UL << 27); //获得第27位上的取值 bool status; status = bitset_quizl[27]; status = int_quizl & (1UL << 27);
通常来说:bitset优于整型数据的低级直接位操作。
//P136 习题5.9 int main() { unsigned int ul1 = 3,ul2 = 7; cout << (ul1 & ul2) << endl; cout << (ul1 | ul2) << endl; cout << (ul1 && ul2) << endl; cout << (ul1 || ul2) << endl; }
//习题5.10 int main() { bitset<30> bitset_quizl; //设置第27位为1 bitset_quizl[27] = 1; cout << bitset_quizl << endl; //设置第27位为0 bitset_quizl[27] = 0; cout << bitset_quizl << endl; cout << bitset_quizl[27] << endl; }
10、移位操作符用于I/O
移位操作符具有中等优先级:其优先级比算术运算符低,但比(1)关系操作符,(2)赋值操作符,(3)条件运算符优先级高。
11、赋值运算符具有右结合性,如:
int ival1,ival2; ival1 = ival2 = 0; //等价与 (ival1 = (ival2 = 0));
//P139 习题5.11 i、d的值分别为? int i; double d; d = i = 3.5; i = d = 3.5;
//习题5.12 下面程序会有什么结果 //(1) int main() { int i; if (42 = i) { //... } }
//(2) int main() { int i; if (i = 42) { //... } }
//P140 习题5.14 下面程序会有什么输出结果 int main() { int ival = 2; ival += (ival + 1); cout << ival << endl; }
12、建议:只有在必要时才使用后置自增/自减操作符
前置操作符需要做的工作更少,而后置操作符必须先保存操作数原来的值,以便返回未加/减1之前的结果。【P140建议...值得仔细品读!】
13、后自增操作符的优先级高于解引用操作符,因此*iter++等价与*(iter++).
【建议阅读:P141建议:简洁即是美】