C语言 位运算

1G=1024M;

1M=102KB;

1KB=1024B(字节);

1B=8bits(位);

#include<stdio.h>
#include<stdlib.h>

//C语言中的逻辑运算符
//逻辑与(&&);逻辑或(||);逻辑非(!)。

//强调逻辑运算符与位逻辑运算符不同

//C语言中的位运算符有以下两类:
//位逻辑运算符:&(位“与”)、^(位“异或”)、 | (位“或”)、~(位“取反”)。
//移位运算符: << (左移)、 >> (右移)
void main(){
    //一:取反运算(~)
    unsigned char ch1 = 165;
    //一个字符有8位,ch1换算成二进制是 1010 0101
    //位取反的操作符为“~”,
    //即每位都取反,0变成1,1变成0,需要注意的是,位取反运算并不改变操作数的值。
    //那么~ch1=0101 1010,换算成十进制是90
    unsigned char ch2 = ~ch1;
    //printf("
%d", ~ch1);//  打印  -166  错误  解释: ~ch1是取反运算,值会存储在cpu的寄存器中,所以printf函数不确定~ch1的类型
    printf("
取反运算%d", (unsigned char)~ch1);//  打印  90  正确
    printf("
取反运算%d",ch2);//  打印  90  正确

    //二:与运算(&)----清零
    //位与运算的操作符为&,将对两个操作数的每一位
    //进行与运算,位“与”运算的准则如下:(两者都为1的时候才是1,有一个为0就是0)
    //1 & 1 = 1     1 & 0 = 0     0 & 1 = 0     0 & 0 = 0
    unsigned char ch3 = 15;
    //ch1        1010 0101
    //ch3        0000 1111
    //ch1&ch3    0000 0101   十进制是5
    unsigned char ch4 = ch1&ch3;
    printf("
与运算%d", ch4);//  打印  5  正确
    //对于ch1&ch3的分析,发现与运算可以用来"保持一部分位不变(不变用1),部分为全部为0(变0用0)"

    //三:或运算(|)---置1
    //位或运算的操作符为|,将对两个操作数的每一位进行或运算,位“或”运算的准则如下:(两者有一个是1就是1,两者都为0才是0)
    //1 | 1 = 1      1 | 0 = 1      0 | 1 = 1      0 | 0 = 0
    //例子
    //ch1        1010 0101
    //ch3        0000 1111
    //ch1|ch3    1010 1111   十进制是175
    unsigned char ch5 = ch1|ch3;
    printf("
或运算%d", ch5);//  打印  175  正确
    //对于ch1|ch3的分析,发现与运算可以用来"保持一部分位不变(不变用0),部分为全部为1(变1用1)"

    //四:异或运算(^)---取反
    //位或运算的操作符为^,将对两个操作数的每一位进行异或运算。
    //通俗地讲,如果位“异或”运算的两个位相同(同为0或同为1),结果为0,
    //若两个位不同(一个为0,另一个为1),结果为1,对应的准则为:(两者相同结果是0,两者不同结果是1)
    //1 ^ 1 = 0  1 ^ 0 = 1  0 ^ 1 = 1  0 ^ 0 = 0
    //例子
    //ch1        1010 0101
    //ch3        0000 1111
    //ch1^ch3    1010 1010  十进制170
    unsigned char ch6 = ch1^ch3;
    printf("
异或运算%d", ch6);//  打印  170  正确
    //对于ch1^ch3的分析,发现与运算可以用来"保持一部分位不变(不变用0),部分取反(取反用1)"

    //五:左移运算(<<)
    //A称为操作数,其必须为数字型变量或数字型常量,
    //此处的数字型包括整型、浮点型和char型,A中存储的0、1序列向左或右移动n位,
    //移动后的值作为整个表达式的输出,执行移位运算并不改变操作数A的值。
    unsigned char ch7 = 1;
    //例子
    //ch7        0000 0001    十进制是1
    //ch7<<1     0000 0010    十进制是2  (1*2)
    //ch7<<2     0000 0100    十进制是4   (2*2)
    unsigned char ch8 = ch7<<1;
    unsigned char ch9 = ch7<<2;
    printf("
左移运算ch7<<1=%d", ch8);//  打印  2  正确
    printf("
左移运算ch7<<2=%d", ch9);//  打印  4  正确
    unsigned char cha = 128;
    //例子
    //cha        1000 0000    十进制是128
    //cha<<1     0000 0000    十进制是0  
    unsigned char chb = cha << 1;
    printf("
左移运算cha<<1=%d", chb);//  打印  0  正确

    //六:右移运算(>>)
    unsigned char chc = 255;
    //例子
    //chc        1111 1111    十进制是255
    //chc>>1     0111 1111    十进制是127  (255/2)
    //chc>>2     0011 1111    十进制是63    (127/2)
    unsigned char chd = chc >> 1;
    unsigned char che = chc >> 2;
    printf("
右移运算chc >> 1=%d", chd);//  打印  127  正确
    printf("
右移运算chc >> 2=%d", che);//  打印  63  正确


    //练习
    // 1010 0101十进制是165
    //练习1:前四位不变,后四位清零
    //分析:清零操作使用与运算符;前四位不变1111,后四位清零0000,二进制是1111 0000---十进制是240
    unsigned char chf = 240;
    unsigned char chg = ch1&chf;
    //ch1        1010 0101    十进制是165
    //chf        1111 0000    十进制是240  
    //ch1&chf    1010 0000    十进制是160
    printf("
前四位不变,后四位清零%d", chg);//  打印  160  正确

    //练习2:前四位不变,后四位置1
    //分析:置1使用或运算符,前四位不变--0000,后四位置1--1111,二进制是 0000 1111---十进制是15
    unsigned char chh = 15;
    unsigned char chi = ch1 | chh;
    //ch1        1010 0101    十进制是165
    //chh        0000 1111    十进制是15  
    //ch1|chf    1010 1111    十进制是175
    printf("
前四位不变,后四位置1--%d", chi);//  打印  175  正确

    //练习3:前四位不变,后四位取反
    //分析:取反有2中方法,取反运算符和异或运算符,取反运算符只能全部取反,异或运算符可以部分取反
    //前四位不变,说明只能使用异或运算符;前四位不变0000;后四位取反1111,二进制是 0000 1111---十进制是15
    //注:异或相同为0,不同为1,两个0的值仍然是0,两个1的值是0,一个0和一个1结果是1
    unsigned char chj = ch1^chh;
    //ch1        1010 0101    十进制是165
    //chh        0000 1111    十进制是15  
    //ch1|chf    1010 1010    十进制是170
    printf("
前四位不变,后四位取反--%d", chj);//  打印  170  正确

    system("pause");
}

     

           在C语言的位运算中,左移也就是所说的逻辑移位,右端补0,而右移是算数移位,左端补齐的是最高位的符号位。因此负数左移,有可能变成正数
,但负数右移,肯定还是负数。

 特别注意,这是运算的变量是有符号类型的情况,如果是无符号类型,就算最高位是1,那么左移填充的符号位依然是0。

位运算注意点
    在进行位运算时,要求所有参与运算变量必须是 unsigned char类型,这是因为正数和负数在内存中都是以补码方式存储
如果使用char,这是有符号的类型,那么如果这个char小于0,那么在内存中的存储就会变化,当出现拷贝操作时,就会改变原数据
如果使用unsigned char,所有的数据都是正数(正数的原码,补码一致),拷贝时,系统就不会修改原数据了
原文地址:https://www.cnblogs.com/zhanggaofeng/p/5140189.html