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

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

文章目录

前言

一、位运算

二、取反

三、运算

四、函数操作 

1、两数交换 

2、改变符号

3、取绝对值

4、判断奇偶性

5、求模

6、两数相加

五、总结


前言

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


一、位运算

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

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

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

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

二、取反

C语言,详解二进制位运算_第1张图片

三、运算

C语言,详解二进制位运算_第2张图片

C语言,详解二进制位运算_第3张图片

C语言,详解二进制位运算_第4张图片

四、函数操作 

1、两数交换 

C语言,详解二进制位运算_第5张图片

C语言,详解二进制位运算_第6张图片

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

2、改变符号

C语言,详解二进制位运算_第7张图片C语言,详解二进制位运算_第8张图片

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

3、取绝对值

C语言,详解二进制位运算_第9张图片

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

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

4、判断奇偶性

C语言,详解二进制位运算_第10张图片 个人感觉这种判断方法更方便

5、求模

 15 % 4 = 3

6、两数相加

C语言,详解二进制位运算_第11张图片

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


五、总结

#include 

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语言,详解二进制位运算_第12张图片

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

你可能感兴趣的:(c语言)