C++ Primer 第4章 表达式(2)

4.8 位运算符

位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。位运算符提供检查和设置二进制位的功能。
如果运算对象是小整型,会被自动提升为较大时整数类型;建议仅用于处理无符号类型。
在这里插入图片描述
移位运算符
对其运算对象执行基于二进制位的移动操作。其右侧的运算对象一定不能为负,而且值必须严格小于结果的位数,否则就产生了未定义的行为,移出边界之外的位就被舍弃掉了。
左移运算符(<<)在右侧插入值为0的二进制位。右移运算符(>>)的行为依赖于其左侧运算对象的类型:若无符号,在左侧插入值为0的二进制位;若带符号,在左侧插入符号位的副本或值为0的二进制位,如何选择视具体情况而定。
在这里插入图片描述
位求反运算符(~)
将运算对象逐位求反生成一个新值,将1置为0,将0置为1.
char类型的运算对象首先提升成int类型,提升时原来的为保持不变,往高位添加0即可。
在这里插入图片描述
位与、位或、位异或运算符
位与(&)运算符:如果两个运算对象的对应位置都是1则运算结果中该位为1,否则为0.
位或(|)运算符:如果两个运算对象的对应位置至少有一个为1则运算结果中该位为1,否则为0.
位异或(^)运算符:如果两个运算对象的对应位置有且只有一个为1,则运算结果中该位为1,否则为0.
在这里插入图片描述
位移运算符满足左结合律,优先级不高不低,介于中间:比算术运算符的优先级低,比关系运算符、赋值运算符和条件运算符的优先级高。

4.9 sizeof运算符

sizeof运算符返回一条表达式或一个类型名字所占的字节数。sizeof运算符满足右结合律,其所得的值是一个size_t类型的常量表达式。运算符的运算对象有两种形式:
sizeof (type) 和 sizeof expr ;
在第二种形式中,sizeof返回的是表达式结果类型的大小。与众不同的一点是,sizeof并不实际计算其运算对象的值。
在这里插入图片描述
sizeof运算符的结果部分地依赖于其作用的类型:
1.对char或者类型为char的表达式执行sizeof运算,结果为1.
2.对引用类型执行sizeof运算,得到被引用对象所占空间的大小。
3.对指针执行sizeof运算得到指针本身所占空间的大小。
4.对解引用指针执行sizeof运算得到指针所指对象所占空间的大小,指针不需有效。
5.对数组执行sizeof运算得到整个数组所占空间的大小,等价于对数组中所有元素各执行一次sizeof运算并将结果求和。sizeof运算不会把数组转换成指针来处理。
6.对string对象和vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中元素占用了多少空间。
可以用数组的大小除以单个元素的大小得到数组中元素的个数,用来声明数组的维度:
在这里插入图片描述

4.10 逗号运算符

逗号运算符含有两个运算对象,按照从左到右的顺序依次求值。首先对左侧表达式求值,然后将求值结果丢弃掉,逗号运算符真正的结果是右侧表达式的值,如果右侧运算对象是左值,那么最终的求值结果也是左值。
在这里插入图片描述
从本质上讲,逗号的作用是将一系列运算按顺序执行。

4.11 类型转换

如果两个类型可以相互转换,那么它们就是关联的。
隐式转换:编译器自动地转换运算对象的类型,无须程序员的介入。下面这些情况下发生隐式转换:
在这里插入图片描述

4.11.1 算术转换

算术转换的含义是把一种算术类型转换成另一种算术类型。算术转换的规则定义了一套类型转换的层次,其中运算符的运算对象将转换成最宽的类型。
整型提升
整型提升负责把小整数类型转换成较大的整数类型。
1.对于bool、char、signed char、unsigned char、short和unsigned short等类型来说,只要它们所有可能的值都能存在int里,它们就会提升提升成int类型;
2.较大的char类型(wchar_t、char1_t、char32_t)提升成int、unsigned int、long、unsigned long、long long和unsigned long long中最小的类型。
无符号类型的运算对象
如果某个运算符的运算对象类型不一致,这些运算对象将转换成同一种类型。
首先执行整型提升。如果结果的类型匹配,无须进行进一步的转换,否则:
1.若两个(提升后的)运算对象的类型要么都是带符号的,要么都是无符号的,则小类型的运算对象转化为大类型的运算对象;
2.若一个是带符号的,一个是无符号的,而且带符号类型小于等于无符号类型,那么带符号的运算对象转换成无符号的;
3.若带符号类型大于无符号类型,如果无符号类型的所有值都能存在该带符号类型中,则无符号类型的运算对象转换成带符号类型,否则,带符号类型的运算对象转换成无符号类型。
在这里插入图片描述
在这里插入图片描述

4.11.2 其他隐式类型转换

除了算术转换之外还有几种隐式类型转换:
数组转换为指针:在大多数用到数组的表达式中,数组会自动转换成指向数组首元素的指针。
当数组被用作decltype关键字的参数,或者作为取地址符(&)、sizeof以及typeid等运算符的运算对象时,上述转换不会发生。
指针的转换:常量整数值0或者字面值nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向任意对象的指针能转化成const void*。
转换成布尔类型:如果指针或算术类型的值为0,转换结果为false,否则为true。
转换成常量:允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。相反的转换并不存在,因为它试图删掉底层const。
在这里插入图片描述
类类型定义的转换:类类型能定义由编译器自动执行的转换,不过编译器每次只能执行一种类类型的转换。
我们之前使用过类类型转换:一处是在需要标准库string类型的地方使用C风格字符串;另一处是在条件部分读入istream,例如while(cin >> s)。条件部分本来需要一个布尔类型的值,但是这里实际检查的是istream类型的值,cin自动地转换成布尔值。

4.11.3 显示转换

强制类型转换:
在这里插入图片描述
命名的强制类型转换
一个命名的强制类型转换具有如下形式:
cast-name< type >(expression);
其中,type是转换的目标类型而expression是要转换的值。如果type是引用类型,则结果是左值。cast-name是static_cast、dynamic_cast、const_cast和reinterpret_cast中的一种。
static_cast
任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。
在这里插入图片描述
当需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用,它告诉编译器不在乎潜在的精度损失,警告信息就会被关闭了。
可以使用static_cast找回存在于void*指针中的值,但必须确保转换后所得的类型就是指针所指的类型:
在这里插入图片描述
const_cast
const_cast只能改变运算对象的底层const(底层const表示指针所指的对象是一个常量)。
在这里插入图片描述
对于将常量对象转换成非常量对象的行为,我们一般称为“去const性质”,一旦我们去掉而来某个对象的const性质,编译器就不会阻止我们对该对象进行写操作了。
只有const_cast能改变表达式的常量属性,其他的命名强制类型都不行,也不能用const_cast改变表达式的类型。
在这里插入图片描述
reinterpret_cast
reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。
在这里插入图片描述
pc所指的真实对象是一个int而非字符,如果把pc当成普通的字符指针使用就有可能在运行时发生错误。
强制类型转换干扰了正常的类型检查,强烈建议避免使用强制类型转换。

4.12 运算符优先级

在这里插入图片描述
在这里插入图片描述

发布了16 篇原创文章 · 获赞 11 · 访问量 644

猜你喜欢

转载自blog.csdn.net/qq_42820853/article/details/104503867