C语言,详解二进制位运算

本文章主要讲解整数的位运算,供大家参考


前言

最近对于二进制的运算挺感兴趣的,在查阅诸多资料,并且自己写了demo后,对于位运算也有了一定的了解,在此记录本次的学习


一、位运算

数据在计算机内部是使用二进制数来储存的,因此使用位运算可以加快程序运行的效率

这些整数是使用补码来储存的,例如

正数  3                                原码 0011        反码 0011         补码 0011

负数 -3                                原码 1011        反码 1100         补码 1101

二、取反

三、运算

四、函数操作 

1、两数交换 

 当然了,当前的交换只在函数内有效,如果想实现真正的交换,需要加上指针操作

2、改变符号

如图所示,取反再加一,即可改变符号 

3、取绝对值

对于正数,绝对值就是他本身

对于负数,绝对值就是取反再加一

4、判断奇偶性

 个人感觉这种判断方法更方便

5、求模

 15 % 4 = 3

6、两数相加

 两数相加的流程就有些麻烦了 


五、总结

#include <stdio.h>

void swap(int a, int b);//两数交换数值
void change_sign(int a);//改变符号
void num_abs(int a);//求绝对值

int main(){
    // 运算时,都是根据补码进行运算的,正数补码与原码一样,而负数则是符号位不变,其余取反,末位加一
    // 取反运算:~
    // 15 原码:0000 1111   补码:0000 1111     ~15 --> 补码:1111 0000 --> 原码:1001 0000 --> -16
    //-15 原码:1000 1111   补码:1111 0001     ~-15 --> 补码:0000 1110 --> 原码:0000 1110 --> 14
    int a = 15, b = 16;
    int res = ~a;

    // ******************************************************************************
    // 与运算 & ,15 & 0 --> 0000 1111 & 0000 0000 = 0000 0000 即为 0
    // 或运算 | ,15 | 0 --> 0000 1111 | 0000 0000 = 0000 1111 即为自己本身
    // 异或运算 ^ 15 ^ -2 --> 0000 1111 ^ 1000 0010 == 0000 1111 ^ 1111 1111 = 1111 0000 --> 1000 1111 = -15
    // -15 ^ 2 --> 1000 1111 ^ 0000 0010 == 1111 0001 ^ 0000 0010 = 1111 0011 --> 1000 1101 即为 -13
    res = a ^ 2;
    printf("异或: a ^ 2 = %d \n\n", res);

    // ******************************************************************************
    // 左移 15 << k  二进制码全部向左移动 k 个,右边补 0  0000 1111 << 1 --> 0001 1110 即为 30
    // 左移 -15 << k    1111 0001 << 1 --> 1110 0010 --> 1001 1110 即为 -30
    // 右移 15 >> k  二进制码全部向右移动 k 个,左边补 0  0000 1111 >> 1 --> 0000 0111 即为 7
    // 右移 -15 >> k    1111 0001 >> 1 --> 1111 1000 --> 1000 1000 即为 -8 
    // 负数左边补 1,右边补 0
    res = a << 1;
    printf("左移: a << 1 = %d \n\n", res);

    // ******************************************************************************
    // 任何数                 << 1 === * 2 
    // 对于偶数来说            >> 1 === / 2
    // 16 << 1    0001 0000 --> 0010 1000 即为 32
    // 16 >> 1    0001 0000 --> 0000 1000 即为 8
    // 对于奇数,则在最后结果上加上0.5
    // 13 >> 1    0000 1101 --> 0000 0110 即为 6
    // 15 >> 1    0000 1111 --> 0000 0111 即为 7
    // 17 >> 1    0001 0001 --> 0000 1000 即为 8
    res = 15 >> 1;
    printf("右移: 15 >> 1 = %f \n\n", res + 0.5);

    // ******************************************************************************
    // 两数交换 1, 2
    // a = 1 ^ 2 --> 0000 0001 ^ 0000 0010 = 0000 0011 = 3
    // b = 2 ^ 3 --> 0000 0010 ^ 0000 0011 = 0000 0001 = 1
    // a = 3 ^ 1 --> 0000 0011 ^ 0000 0001 = 0000 0010 = 2
    // 交换完之后即为 2, 1
    swap(1, 2);

    // ******************************************************************************
    // 改变符号 -2
    // ~-2 + 1 --> 1000 0010 --> 1111 1110 --> 0000 0010 即为 2 
    // ~2 + 1  --> 0000 0010 --> 1111 1110 --> 1000 0010 即为 -2
    change_sign(-2);

    // ******************************************************************************
    // 求绝对值
    // 正数便返回正数
    num_abs(-2);

    // ******************************************************************************
    // 判断奇偶性  与 1 相与
    // 5 & 1 --> 0000 0101 & 0000 0001 = 0000 0001 = 1  奇数
    // 6 & 1 --> 0000 0110 & 0000 0001 = 0000 0000 = 0  偶数
    if (a & 1)
        printf("奇数\n\n");
    else
        printf("偶数\n\n");

    // ******************************************************************************
    // 求模  但是得是 2的k次方
    // 15 & (4 - 1) --> 0000 1111 & 0000 0011 = 0000 0011 = 3 即为 15 % 4 = 3
    printf("求模: a & (4 - 1) = %d \n\n", a & (4 - 1));

    // ******************************************************************************
    a = 13;
    b = 7;
    // 两数相加 13 + 7
    // 0000 1101 ^ 0000 0111 = 0000 1010 = 10
    // 0000 1101 & 0000 0111 = 0000 0101 << 1 --> 0000 1010 = 10
    // a = 10   b = 10
    // 0000 1010 ^ 0000 1010 = 0000 0000 = 0
    // 0000 1010 & 0000 1010 = 0000 1010 << 1 --> 0001 0100 = 20
    // a = 0    b = 20
    // 0000 0000 ^ 0001 0100 = 0001 0100 = 20
    // 0000 0000 & 0001 0100 = 0000 0000 << 1 --> 0000 0000 = 0
    // a = 20   b = 0
    // 循环结束,最后结果为 20
    while(b){
        int temp_a = a ^ b;
        int temp_b = (a & b) << 1;
        a = temp_a;
        b = temp_b;
    }
    printf("相加: 13 + 7 = %d\n\n", a);

    return 0;
}

void swap(int a, int b){
    printf("交换前: a = %d, b = %d\n", a, b);
    a ^= b;
    b ^= a;
    a ^= b;
    printf("交换后: a = %d, b = %d\n\n", a, b);
}

void change_sign(int a){
    printf("改变前的值: %d\n", a);
    printf("改变后的值: %d\n\n", ~a + 1);
}

void num_abs(int a){
    printf("求绝对值前的值: %d\n", a);
    // -2 >> 31 得到的是 -1
    // 负数右移,在左边补1,之后转成原码,即为 -1
    printf("求绝对值后的值: %d\n\n", a ^ (a >> 31) ? a : ~ a + 1);
}

以上就是本人整理的有关C语言位运算的操作了,希望对大家有帮助

  • 5
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值