12-bit_operation

来源:互联网 发布:java实战项目视频 编辑:程序博客网 时间:2024/04/29 19:44
位运算符
在C语言中的位运算符
    &    按位与
    |    按位或
    ^    按位亦或
    <<    左移
    >>    右移
    ~    按位取反(单目运算符)

结合律 a&b&c <=> (a&b)&c <=> a&(b&c)
交换律 a&b <=> b&a

左移和右移注意点
左移运算符<<将运算数的二进制位左移,高位丢弃,低位补0;
右移运算符>>把运算数的二进制位右移,高位补符号位,低位丢弃;

0x1 << 2 + 3 的值会是什么
实际上+-运算的优先级高于移位操作

防错准则:
避免位运算符/逻辑运算符和数学运算符同时出现在一个表达式中;
当位运算符/逻辑运算符和数学运算符同时参与运算时,尽量使用()来表达计算次序;

如何交换两个变量的值

#include <stdio.h>
#define SWAP1(a,b) \
{                  \
    int temp = a;  \
    a = b;         \
    b = temp;      \
} //需要使用额外的变量才可以完成

#define SWAP2(a,b) \
{                  \
    a = a + b;     \
    b = a - b;     \
    a = a - b;     \
} //a和b很大的时候a+b会溢出

#define SWAP3(a,b) \
{                  \
    a ^= b;     \
    b ^= b;     \
    a ^= b;     \
}
/*
 * a ^= b; => (a^b)
 * b ^= a; => b^(a^b) => a^(b^b) => a^0 => a
 * a ^= b; => (a^b)^(a) => a^a^b => 0^b =>b
 * 该方法不用借助其他变量,也不会溢出
 * 而且运算效率高于普通的数学运算
 */

int main() {
    int a = 1;
    int b = 2;
    SWAP1(a,b);
    SWAP2(a,b);
    SWAP3(a,b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

练习:
假设有一数列A,其中的自然数都是出现偶数次,只有一个自然数出现的次数为奇数次,编程找出这个自然数;
方法1:
    1.排序
    2.遍历查找
    //缺点,排序太耗时
方法2:
    1.遍历,找出最大值max
    2.申请array[max]
    3.遍历,将array[A[i]]++;
    4.判断哪个下标对应的数值是奇数
方法3;
    考虑到亦或位操作及交换律,将所有元素亦或操作即可得到该自然数

#include <stdio.h>
int main() {
    int a[] = {2, 3, 3, 5, 7, 2, 2, 2, 5, 7, 1, 1, 9};
    int find = 0;
    int i = 0;

    for (i = 0; i < sizeof(a)/sizeof(*a); i++) {
        find ^= a[i];
    }
    printf("find = %d\n", find);
    return 0;
}
思考:
&&,||,!与&,|,~的意义是否相同?它们可以在条件表达式中交替使用码?
    //不同,一种是逻辑操作,一种是位操作;
1<<32的结果是什么?1<<-1的结果又是什么?//0,0

0 0