操作符详解(C语言)—算数操作符,移位操作符,位操作符

操作符的分类

算术操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

下标引用、函数调用和结构成员

算术操作符

+    -    *    /    %
  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
  3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
int main()
{
    int a = 3 / 5;
    printf("%d", a);
    return 0;
}

结果是0,因为a是整型变量

那么我想问,如果是这样呢

int main()
{
    float a = 3 / 5;
    printf("%f", a);
    return 0;
}

我们来看结果

image-20240320171001486

其实这里应该这样子理解,是先3/5得到一个数字,放在了a里面,因为3和5都是整数,所以自动进行整数的运算,如果真的想要小数的话

需要除号的两端至少有一个小数

int main()
{
    float a = 3.0 / 5.0;
    printf("%f", a);
    return 0;
}

image-20240320171207030

移位操作符

<< 左移操作符
>> 右移操作符
    
注:移位操作符的操作数只能是整数。
int main()
{
    int a = 2;
    //把a的二进制位向左移动一位
    int b = a << 1;
    printf("%d", b);
    return 0;
}

我们一起来看一下,整型变量,四个字节,三十二个比特位,所以a的二进制真值就应该是

00000000 00000000 00000000 00000010

我们向左移动一位(这里实际上是全部的二进制码向左移动一位,左边的不要,右边加个0)

00000000 00000000 00000000 00000100

所以b的值转换为2进制就应该是4

我们来看结果

image-20240320172236242

左移操作符,左边丢弃,右边补0;

右移

int main()
{
    int a = 10;
    //把a的二进制位向右移动一位
    int b = a >> 1;
    printf("%d", b);
    return 0;
}

a的真值就是

00000000 00000000 00000000 00001010

右移一位

  • 算数右移

    右边丢弃,左边补原符号位

  • 逻辑右移

    右边丢弃,左边补0

00000000 00000000 00000000 00000101

所以呢这里应该是5

image-20240320173837099

我们使用的是算数右移还是逻辑右移呢?

我们一起来测试一下

int main()
{
    int a = -1;
    //把a的二进制位向右移动一位
    int b = a >> 1;
    printf("%d", b);
    return 0;
}

image-20240320174034825

这里还是-1,说明计算机采用的是算数右移

这里为什么是-1而不是0呢?

计算机在存储整数使用的是补码,所以-1的补码是

11111111 11111111 11111111 11111111

右移之后再补符号位依旧是这个,所以右移之后输出的依然是-1

警告⚠ :

对于移位运算符,不要移动负数位,这个是标准未定义的。

int num = 10;
num>>-1;//千万不要这么写,这么写编译器都看不懂

位操作符

& //按位与     全真为真
| //按位或     有真为真
^ //按位异或   相异为真
注:他们的操作数必须是整数。
按位与
int main()
{
    int a = 3;
    int b = 5;
    int c = a & b;
    //
    //a的二进制真值 00000000 00000000 00000000 00000011
    //b的二进制真值 00000000 00000000 00000000 00000101
    //按位与        00000000 00000000 00000000 00000001
    printf("%d", c);
    return 0;
}

我们看一下结果

image-20240320175053450

按位或
int main()
{
    int a = 3;
    int b = 5;
    int c = a | b;
    //
    //a的二进制真值 00000000 00000000 00000000 00000011
    //b的二进制真值 00000000 00000000 00000000 00000101
    //按位或        00000000 00000000 00000000 00000111
    printf("%d", c);
    return 0;
}

image-20240320175327355

按位异或
int main()
{
    int a = 3;
    int b = 5;
    int c = a ^ b;
    //
    //a的二进制真值 00000000 00000000 00000000 00000011
    //b的二进制真值 00000000 00000000 00000000 00000101
    //按位异或      00000000 00000000 00000000 00000110
    printf("%d", c);
    return 0;
}

image-20240320175444612

面试题

如何交换两个变量的值,不能使用第三个变量,即a=3,b=5,交换后a=5,b=3?

先思考一分钟

一般来说,我们都是这样子实现的

c = a;
a = b;
b = c;

揭晓答案

方法1:

a = a + b;
b = a - b;
a = a - b;

但是这种方法其实有缺陷,如果数值太大是有可能出现溢出的情况的

方法2:

异或

a = a ^ b;
b = a ^ b;
a = a ^ b;

我们先来验证一下

int main()
{
    int a = 3;
    int b = 5;

    printf("a = %d b = %d\n", a, b);

    a = a ^ b;
    b = a ^ b;
    a = a ^ b;

    printf("a = %d b = %d\n", a,b);
    return 0;
}

image-20240320180705850

我们来简单分析一下

a = 3     二进制     011
b = 5     二进制     101
    
a = a ^ b;          110
     
b = a ^ b;          011
    
a = a ^ b;          101
    
a = 5     二进制     101
b = 3     二进制     110

我们其实可以这样子理解

我们把a和b进行按位或,也就是说我们通过a和b生成了一个密码,这个密码由a和b得到
    
我们使用b进行译码,就能得到a
    
我们使用a进行译码,就能得到b

好,那么今天先到这,剩下的操作符明天再说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J.Pei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值