c++|超详细的操作符解析
还记得之前对操作符进行了简单的了解,并且学习了一些常见操作符的用法,如今我们又对操作符这部分的知识进行了更深一步的学习,有了一些新的感悟和体会,这篇文章我希望能把关于操作符的方方面面,包括一些细微之处,都说到位。
话不多说,让我们开始吧!
一.操作符分类
- 操作符有哪些?可以分为几类:
- 算术操作符
- 移位操作符
- 位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号表达式
- 下标引用、函数调用和结构成员
二.算术操作符
+-*/%关于算数操作符,比较简单,这里说一些需要注意的:
1.除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除 法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
三.移位操作符
<<左移操作符这是我们今天要重点介绍的操作符之一
>>右移操作符
注:他们的操作数必须是整数。
1.有关进制和原码、反码、补码
int a = 5;
int b = a << 2;
这里的 a<<2 是把a向左移动2位,实质是:把a在内存中存储的二进制位向左移动两位
这里补充一下进制的知识:
下面用一张图来帮助我们理解进制基数为2,数值部分用两个不同的数字0、1来表示。
- 二进制:逢二进一
基数为10,数值部分用0、1、2、3、4、5、6、7、8、9来表示.
- 十进制:逢十进一
基数是16,有十六种数字符号,除了在十进制中的0至9外,还另外用6个英文字母A、B、C、D、E、F来表示十进制数的10至15。
- 十六进制:逢十六进一
文章图片
下面我们还需要了解一下原码 、反码 、补码的知识 :
整数有3种二进制表示形式:
- 原码
- 反码
- 补码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制
[+1]原码 = 0000 0001(2).反码
[-1] 原码 = 1000 0001
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1]=[00000001]原码=[00000001]反码(3).补码
[- 1]=[10000001]原码=[111111110]反码
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1]=[00000001]原=[00000001]反码=[00000001]补码经过上面的叙述,我们很容易发现;
[-1]=[10000001]原=[11111110] 反码=[11111111]补码
- 正整数:原码、补码、反码相同
- 负整数:原码、补码、反码不同,需要计算
文章图片
而整数在内存中存储的是补码!!!
文章图片
如图,-1的在内存中存储的是补码
而VS编译器是16进制展示
所以显示的内存是 f ff ff ff f
我们知道16进制的 f 就是10进制的15,所以这里对应的就是-1的补码
2.移位操作符
首先需要说明的是:
移位操作符操作的是补码
而打印或使用的时候,用的是补码
所以使用移位操作符会某个数的二进制的补码改变后,我们如果需要打印或使用这个数的二进制是,要先通过改变后的补码反推出改变后的原码
铺垫做的差不多了,下面正式介绍移位操作符 !
(1).左移操作符
移位规则:左边抛弃、右边补0
文章图片
如图,通过左移操作符把num向左移了一位, 正数10的二进制的补码 左边抛弃、右边补0
变成了 00000000000000000000000000010100
计算结果就为 1*2^4+1*2^2=20 了
如果要打印
int num2=num<<1;
printf("%d",num2);
这里的打印用的是num2的原码的值
需要注意的是:
这时num的值还是10,没有改变,只是我们计算了一下 num<<1 的结果而已
(2).右移操作符
移位规则:
首先右移运算分两种:
- 算术移位 :左边用原该值的符号位填充,右边丢弃
- 逻辑移位:左边用0填充,右边丢弃
如果是正数,这两种结果一样
我们通过一张图来展示一下右移操作符的作用效果
文章图片
我们用一个负数 -5 来看一下
文章图片
经过算术操作符,结果是 -3
经过逻辑操作符,结果是3
警告? :
对于移位运算符,不要移动负数位,这个是标准未定义的行为。
如
int b = a >> -2;
这是不行的!
四.位操作符位操作符有:
&//按位与注:他们的操作数必须是整数。
|//按位或
^//按位异或
这里的”位“指的都是二进制位
& 按位与 (对应的二进制位有0则为0,全1才为1)
|按位或(有1为1,全0为0)
^按位异或 (相同为0,相异为1)
(1).&按位与
我们举个例子
int a = 3 ;
int b = -5 ;
int c = a & b ;
我们用一张图表示运算的过程:
文章图片
(2). |按位或
int a = 3 ;
int b = -5 ;
int c = a | b ;
文章图片
结果是 -5
(3). ^按位异或
int a = 3 ;
int b = -5 ;
int c = a ^ b ;
文章图片
【c++|超详细的操作符解析】结果是 -8
下面我们看曾经一道变态的面试题
不能创建临时变量(第三个变量),实现两个数的交换。
首先我们应该明确:
a ^ a = 0上代码!
a ^ 0 = a
#include
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("a = %d b = %d\n", a, b);
return 0;
}
一个练习:
编写代码实现:求一个整数存储在内存中的二进制中1的个数。
//方法1
#include
int main()
{
int num= 10;
int count=0;
//计数
while(num)
{
if(num%2 == 1)
count++;
num = num/2;
}
printf("二进制中1的个数 = %d\n", count);
return 0;
}
//思考这样的实现方式有没有问题?
//方法2:
#include
int main()
{
int num = -1;
int i = 0;
int count = 0;
//计数
for(i=0;
i<32;
i++)
{
if( num & (1 << i) )
count++;
}
printf("二进制中1的个数 = %d\n",count);
return 0;
}
//思考还能不能更加优化,这里必须循环32次的。
//方法3:
#include
int main()
{
int num = -1;
int i = 0;
int count = 0;
//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("二进制中1的个数 = %d\n",count);
return 0;
}
//这种方式是不是很好?达到了优化的效果,但是难以想到。
五.赋值操作符赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
int weight = 120; //体重赋值操作符可以连续使用,比如:
weight = 89; //不满意就赋值
double salary = 10000.0;
salary = 20000.0; //使用赋值操作符赋值。
int a = 10;
int x = 0;
int y = 20;
a = x = y+1;
//连续赋值
a的结果是21,这样写是没错,但不建议这样写
复合操作符
+=这些运算符都可以写成复合的效果。 比如:
-=
*=
/=
%=
>>=
<<=
&=
|=
^=
int x = 10;
x = x+10;
x += 10;
//复合赋值
//其他运算符一样的道理。这样写更加简洁。
六.单目操作符
!逻辑反操作
-负值
+正值
&取地址
sizeof操作数的类型长度(以字节为单位)
~对一个数的二进制按位取反
--前置、后置--
++前置、后置++
*间接访问操作符(解引用操作符)
(类型)强制类型转换
文章图片
(1).逻辑反操作符 !
如:
int flag = 0;
则!flag = 1
若
int flag = 5;
则 !flag = 0
注:!flag的结果只能为1或0(真或假)
推荐阅读
- opencv|opencv C++模板匹配的简单实现
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- c++基础概念笔记
- 牛逼!C++开发的穿越丛林真人游戏,游戏未上线就有百万人气
- 适用于小白(VSCode搭建Vue项目,最详细的搭建步骤哦)
- C++Primer之|C++Primer之 函数探幽
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- QML基础信息
- C++-类型转换
- MongoDB|MongoDB - 简介