C++ Primer 学习笔记_16_表达式 -算术、关系、逻辑、位、赋值、自增/自减操作符

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整型操作数。

C++ Primer 学习笔记_16_表达式 -算术、关系、逻辑、位、赋值、自增/自减操作符

   1<< n :相当于1* 2^n

   m<< n :相当于m* 2^n


9bitset对象与整型值的使用对比

	//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建议:简洁即是美