13. 位运算符分析----注意区分逻辑运算符和位运算符

在C语言中的位运算符

& 按位与

2&3     相当于 010 & 011 = 010   十进制就是:2

| 按位或

2 | 3     相当于 010 | 011 = 011   十进制就是:3

^按位异或(不同是1)

2 ^ 3     相当于 010 ^ 011 = 001   十进制就是:1

结合律:a&b&c 等价于 (a&b)&c 等价于 a&(b&c)

交换律:a&b 等价于 b&a

“&、|、^”均适合交换律和结合律

左移和右移注意点:

左移运算符<<将运算数的二进制位左移

规则:高位丢弃(高位移动出界的丢弃,少的补零),低位补0            

    1<<2    :     0001变成0100

右移运算符>>把运算数的二进制位右移

规则:高位补符号位(正补0填充高位,负补1填充高位),低位丢弃(

低位出界的丢弃对吗?)    

    8>>3:   0000 1000变成0000 0001

   -8>>3:   1111 1000变成1111 1111

取反:~8 :从1000变成0111

易错:(优先级问题)

0x1<<2+3是先算2+3,再算左移,最后32

(0x1<<2)+3 = 7

防错准则:

  • 避免位运算符,逻辑运算符和数学运算符同时出现在一个表达式中
  • 当位运算符,逻辑运算符和数学运算符需要同时参与运算时,尽量使用括号()来表达计算次序

左移n位相当于乘以2的n次方,但效率比数学运算符高

3<<4 : 0000 0011变成0011 0000  是48,即3×(2的4次方)

右移n位相当于除以2的n次方,但效率比数学运算符高

8>>4 :0 1000变成 0000 0001 是1,即8÷(2的3次方)

交换两个变量分析(逻辑运算符妙用)

#define SWAP1(a,b) \
{                  \
    int temp = a;  \
    a = b;         \
    b = temp;      \
}
#define SWAP2(a,b) \
{                  \
    a = a + b;     \
    b = a - b;     \
    a = a - b;     \
}//不借用第三个变量,数据较大时不可行,会溢出
#define SWAP3(a,b) \
{                  \
    a = a ^ b;     \
    b = a ^ b;     \
    a = a ^ b;     \
}//都是按位运算,不可能溢出,"^"异或;浮点数不行;效率高

位运算题:

有一个数列(2,3,4,5,2,2,2,4,5,3,1,1,1),其中的自然数都是以偶数的形式出现,只有一个自然数出现的次数为奇数次。编写程序找出这个自然数。(异或,交换律)

#include <stdio.h>
#define DIM(a) (sizeof(a)/sizeof(*a))
int main()
{
    int a[] = {2,3,4,5,2,2,2,4,5,3,1,1,1};
    int find = 0;
    for(int i = 0; i < DIM(a); i++)
    {
        find = find^a[i];
    }
    printf("find = %d\n", find);
    return 0;
}

思考:

&&, ||, !与&, |, ~的意义是否相同?它们可以在条件表达式中交替使用吗?为什么?

不能交替使用,逻辑运算符和位运算符的语义不同。逻辑运算符考虑操作数的真值(即,它们将操作数视为布尔值,真或假),而位运算符考虑操作数的每一位。因此,在条件表达式中使用逻辑运算符通常更为合适,因为它们直接处理布尔值,这与条件表达式的期望输入相匹配。

 1<<32的结果是什么?1<<-1的结果又是什么?为什么?

0000 0001 左移32,溢出,变成0

0000 0001 左移-1,相当于右移1,溢出,变成0

在大多数现代系统上,一个int类型通常是32位的。当尝试将一个32位的整数左移32位时,实际上是在请求一个不可能的操作:将一个32位的数完全移出其表示范围。这种行为是未定义的,因为标准没有规定在这种情况下应该如何处理。在某些编译器和平台上,结果可能是0(因为所有位都被移出了),但这并不是由语言标准保证的。

左移一个负数位同样是未定义行为。位移的数量应该是非负的,因为负位移在逻辑上没有意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值