您的位置:首页 > 编程语言 > C语言/C++

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

2015-11-06 12:07 716 查看

表达式
--算术关系逻辑位赋值自增自减操作符

正文

表达式

--算术、关系、逻辑、位、赋值、自增/自减操作符

引:

   除了特殊用法,表达式的结果为右值:可以读取结果值,但是不能对其进行赋值。
   高优先级的操作符要比低优先级的结合得更紧密。

正文:

1、某些算术表达式的求解结果未定义:一部分有数学特性决定,如除0操作;另一部分则归咎于计算机特性,如溢出。

2、除法和求模操作:
   1)如果两个操作数都是负数:则除法操作的结果为正数,而求模操作结果为负数
   2)如果只有一个操作数是负数:这两种操作的结果都要取决于机器:求模结果的符号要取决于机器,除法操作的值则是负数。

[cpp]
view plaincopyprint?





cout << -21 % -8 << endl;  
cout << 21 % -5 << endl;    //1 or -4  
  
cout << -21 / -8 << endl;  
cout << 21 / -5 << endl;    //-4 or -5  

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。

[cpp]
view plaincopyprint?





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;  

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、不应该串接使用关系操作符,如:

[cpp]
view plaincopyprint?





if (i < j < k)  
{  
    //...  
}  

if (i < j < k)
{
//...
}


该表达式的结果往往是出人意料的:这种写法只要k值大于1,则该表达式的结果就为true;

[cpp]
view plaincopyprint?





//P133 习题5.7  
int main()  
{  
    int val;  
    while (cin >> val && val != 42)  
    {  
        //...  
    }  
}  

//P133 习题5.7
int main()
{
int val;
while (cin >> val && val != 42)
{
//...
}
}


[cpp]
view plaincopyprint?





//习题 5.8  
    if (a > b && b > c && c > d) {//...}  

//习题 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对象与整型值的使用对比

[cpp]
view plaincopyprint?





//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对象的每一位都默认为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优于整型数据的低级直接位操作。

[cpp]
view plaincopyprint?





//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;  
}  

//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;
}


[cpp]
view plaincopyprint?





//习题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;  
}  

//习题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、赋值运算符具有右结合性,如:

[cpp]
view plaincopyprint?





int ival1,ival2;  
ival1 = ival2 = 0;  
//等价与  
(ival1 = (ival2 = 0));  

int ival1,ival2;
ival1 = ival2 = 0;
//等价与
(ival1 = (ival2 = 0));


[cpp]
view plaincopyprint?





//P139 习题5.11 i、d的值分别为?  
    int i;  
    double d;  
    d = i = 3.5;  
    i = d = 3.5;  

//P139 习题5.11 i、d的值分别为?
int i;
double d;
d = i = 3.5;
i = d = 3.5;


[cpp]
view plaincopyprint?





//习题5.12 下面程序会有什么结果  
//(1)  
int main()  
{  
    int i;  
    if (42 = i)  
    {  
        //...  
    }  
}  

//习题5.12 下面程序会有什么结果
//(1)
int main()
{
int i;
if (42 = i)
{
//...
}
}


[cpp]
view plaincopyprint?





//(2)  
int main()  
{  
    int i;  
    if (i = 42)  
    {  
        //...  
    }  
}  

//(2)
int main()
{
int i;
if (i = 42)
{
//...
}
}


[cpp]
view plaincopyprint?





//P140 习题5.14 下面程序会有什么输出结果  
int main()  
{  
    int ival = 2;  
    ival += (ival + 1);  
    cout << ival << endl;  
}  

//P140 习题5.14 下面程序会有什么输出结果
int main()
{
int ival = 2;
ival += (ival + 1);
cout << ival << endl;
}

12、建议:只有在必要时才使用后置自增/自减操作符
    前置操作符需要做的工作更少,而后置操作符必须先保存操作数原来的值,以便返回未加/减1之前的结果。【P140建议...值得仔细品读!】

13、后自增操作符的优先级高于解引用操作符,因此*iter++等价与*(iter++).
    【建议阅读:P141建议:简洁即是美】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息