C for ios --- 位运算

位运算符介绍(一)


1.什么是位运算符?

  • 位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。 C语言��供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的 char,short,int与long类型。

2.位运算符与

  • & 按位与

    • 只有对应的两个二进位均为1时,结果位才为1,否则为0
    • 口诀: 同1为1
  • 示例:

~~ 9&5 = 1
~~ 
~~  1001
~~ &0101
~~ ------
~~  0001
  • 规律

    • 二进制中,与1相&就保持原位,与0相&就为0
  • 应用场景:

    • 按位与运算通常用来对某些位清0或保留某些位。例如把a的高位都清0,保留低八位,那么就a&255
    • 判断奇偶: 将变量a与1做位与运算,若结果是1,则 a是奇数;若结果是0,则 a是偶数
    • 任何数和1进行&操作,得到这个数的最低位
~~   1001
~~ & 0001
~~ ------------
~~   0001
 ```
'' + 想把某一位置0

~~ 11111111
~~ & 11111011
~~ ————
~~ 11111011

---

## 3.位运算符或
- | 按位或
    + 只要对应的二个二进位有一个为1时,结果位就为1,否则为0

- 示例

 ```
~~ 9|5 = 13
~~ 
~~  1001
~~ |0101
~~ ------
~~  1101
 ```
---

## 4.位运算符异或
- ^ 按位异或
    + 当对应的二进位相异(不相同)时,结果为1,否则为0

- 示例

~~ 9^5 = 12
~~
~~ 1001
~~ ^0101
~~ ——
~~ 1100
“`

  • 规律
    • 相同整数相^的结果是0。比如5^5=0

* 任何数异或另一个数两次,还是原数本身

5.位运算符取反

  • \~ 取反

    • 各二进位进行取反(0变1,1变0)
    • 多个整数相^的结果跟顺序无关。比如5^6^7=5^7^6
    • 因此得出结论:a^b^a = b
  • 示例

~~ ~9 =-10
~~ 
~~ 9的原码:0000 0000 0000 0000 0000 1001
~~    反码:1111 1111 1111 1111 1111 0110
~~ 
~~ 知道补码求原码:也是符号位不变,其他各位取反+1
~~ 1111 1111 1111 1111 1111 0110
~~ 取反
~~ 1000 0000 0000 0000 0000 1001
~~ +1
~~ 1000 0000 0000 0000 0000 1010 // -10
~~ 

6.练习

  • 判断一个数的奇偶性,如果是奇数则打印“奇数”,否则打 印“偶数”
~~ int a = num&1;
~~ If(a){
~~     printf("奇数");
~~ }else{
~~     printf("偶数");
~~ }
 ```
- 面试题使用位运算实现交换两个数的值

 ```
    //
//  main.c
//  位运算符demo
//
//  Created by D9ingCompany on 2017/3/24.
//  Copyright © 2017年 D9ingCompany. All rights reserved.
//

/**
 swap ab value

 @param argc <#argc description#>
 @param argv <#argv description#>
 @return <#return value description#>
 */
#include <stdio.h>

void swapNormal(int,int);
void swapBigger(int,int);
void swapSupper(int,int);

int main(int argc, const char * argv[]) {
    int a = 5;
    int b = 10;
    printf("交换前a = %i,b = %i\n",a,b);
    swapSupper(a, b);
//    swapNormal(a, b);

//    swapBigger(a, b);
    return 0;
}

/**
 位运算交换

 @param a <#a description#>
 @param b <#b description#>
 */
void swapSupper(int a,int b ){
    a = a^b;
    b = a^b;
    a = a^b;
    printf("a = %i,b = %i\n",a,b);
}

/**
 运算交换

 @param a <#a description#>
 @param b <#b description#>
 */
void swapBigger(int a, int b )
{
    a = a+b;
    b = a-b;
    a = a-b;
    printf("a = %i,b = %i\n",a,b);
}

/**
 容器交换

 @param a <#a description#>
 @param b <#b description#>
 */
void swapNormal(int a,int b){

    int tmp = a;
    a = b;
    b = tmp;
    printf("a = %i,b = %i\n",a,b);

}

位运算符介绍(二)

1.左移位运算符

  • 把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2的n次方

    • 由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
  • 示例

~~ 2<<1; //相当于 2 *= 2 // 4
~~ 2<<2; //相当于 2 *= 2^2; // 8
  • 应用场景
    • 快速计算一个数乘以2的n次方
    • 左移动就是乘以2的n次方

2.右移位运算符

  • 把整数a的各二进位全部右移n位,保持符号位不变。右移n位其实就是除以2的n次方

    • 为正数时, 符号位为0,最高位补0
    • 为负数时,符号位为1,最高位是补0或是补1
    • 取决于编译系统的规定
  • 示例

~~ 2>>1; //相当于 2 /= 2 // 1
~~ 4>>2; //相当于 4 /= 2^2 // 1
~~ 
  • 应用场景
    • 快速计算一个数除以2的n次方

+ 右移就是一个数除以2的n次方

负数的左移右移

  • 负数的左移右移是补码再移动,负数是以补码的形式存储在内存中

3.练习

  • 写一个函数把一个10进制数按照二进制格式输出
  • 分析
~~ 13 -----> 0000 0000 0000 0000 0000 0000 0000 1101
~~ 0000 0000 0000 0000 0000 0000 0000 1101 13
~~ 0000 0000 0000 0000 0000 0000 0000 0001 1
~~ 每次取 一个数的最后一个二进制位
~~ 任何一个数和1进行&(按位与)得到任何一个数的二进制的最后
~~ 一位
  • 实现
~~     int len = sizeof(int)*8;
~~     int temp;
~~     for (int i=0; i<len; i++) {
~~         temp = num; //每次都在原数的基础上进行移位运算
~~         temp = temp>>(31-i); //每次移动的位数
~~         int t = temp&1; //取出最后一位
~~         if(i!=0&&i%4==0)printf(" "); printf("%d",t);
~~     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值