C语言-第12课

第12课 - 位运算符分析

 

  1. 位运算符

&

按位与

~

取反

|

按位或

<<

左移

^

按位异或

>>

右移

C语言是嵌入式开发的首选,我们在进行嵌入式开发的,串口和并口的使用的时候。我们还是要使用位运算的,这样可以更加方便的操作。

结合律:a&b&c = (a&b)&c = a&(b&c)

交换律:a&b = b&a

  1. 左移和右移的注意事项

左移:

左移运算符<<将运算数的二进制位左移,规则是:高位丢弃,地位补0

右移:

右移运算符>>把运算数的二进制位右移,规则是:高位补符号位,地位丢弃。

 

 

l 0x1<<2+3的值会是什么?

先算2+3,所以结果为32。加减法的优先级高于位运算符。但是,这种东西,经常慧然人混淆,所以我们引出放错准则。

  1. 防错准则

避免位运算符,裸机运算符和数学运算符同时出现在一个表达式中。

当位运算符,逻辑运算符和数学运算符需要同时参与运算的时候,尽量使用括号()来表达计算。

小技巧:

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

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

 

  1. 交换两个变量分析

#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;     

}

\ 仅仅用了两个变量

#define SWAP3(a,b)

{                  

    a = a ^ b;     

    b = a ^ b;     

    a = a ^ b;     

}

/*(1)a = a ^ b;

  (2)b = a ^ b = a ^ b ^ b = a ^ (b ^ b) = a ^ 0 = a;

  (3)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);  

    return 0;

}

第三种方法很好,因为位运算符是比加减法的运算效率还要高的。

 

  1. 面试题详解:

有一个数列,其中的自然数都是以偶数的形式出现,只有一个自然数出现的次数为

奇数次。编写程序找出这个自然数。

自己编写的函数(找奇数,弄错了):

#include<stdio.h>

int main()

{

int a[10] = {2,4,6,3,0,12,88,8,10,14};

int i;

int k;

int m;

for(i=0;i<10;i++)

{

k = a[i] % 2;

if(k == 1)

m = a[i];

}

printf("%d ",m);

return 0;

}

运算结果:3

教程中的例子:

#include<stdio.h>

#define DIM(a) (sizeof(a)/sizeof(*a))

int main()

{

int a[] = {2, 3, 5, 7, 2, 2, 2, 3, 5, 7, 1, 1, 1};

int find =0;

int i;

for(i=0;i<DIM(a);i++)

{

find = find ^ a[i];

}

printf("find = %d ",find);

return 0;

}

运行结果:find = 1

  1. 思考

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

不可以,一个是针对数字,一个是语句中的变量。

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

1默认为unsigned int1左移33位,1已经移出左侧最高位,得到的是0

1Lunsigned long int1左移33位得到的数据是0x0000000400000000

1<<-1的结果是0

原文地址:https://www.cnblogs.com/free-1122/p/9706878.html