今晚是平安夜,首先祝大家平安夜快乐,明天是圣诞,祝大家圣诞快乐!!
好了,这周都特别有空,上班也非常轻松,基本就是看看内核驱动,学学安卓,没什么正事的开发活干.今晚,我们来总结一例在现实开发中非常重要的知识点----C语言的位操作。不得不说,我看到很多学习C的小伙伴都不知道到 << >> ~ ! &=~ |=这些符号的具体含义,甚至乱用,混用!!!甚至连学了几年C的都犯浑!! 所以,今天有必要再这里做这个总结,和大家一起来探讨这个常见而又难以学通的知识点。
请记住!没有简单的程序,只有头脑简单的程序员!!
这些知识点太太太太太重要了,如果你连这些都不会,你根本连踏进嵌入式开发或者从事单片机开发这个门你都进不去~~
1、 符号:&
这个叫做按位与
(1)位与:是在二进制中,分别对每一位进行与操作
例如: 1110 &0011 = 0010
它的特点就是:只有1和1位与结果为1 ,其余全是0
这里特别要注意和&&逻辑与区分:位与是两个操作数按照二进制位彼此对应位相与的,逻辑与是两个操作数作为整体来相与的。
逻辑与&&:顾名思义返回值就是个逻辑值1或者0,也就是非真即假!
例如:0xaa & 0xf0 = 0xa0 , 0xaa
&& 0xf0 = 1
2、符号:|
这个叫做按位或
(2)位或:是在二进制中,分别对每一位进行或操作
Ep:1110 & 0011= 1111
特点:只有两个0相或才为0,其余情况都为1,即有1为1
注意和||逻辑或区分:位或是练歌操作数按照二进制位彼此对应位相或的,逻辑或是两个操作数作为整体来相或的。
逻辑或||:顾名思义就是返回值不是真就是假,但和逻辑与就不要搞混淆咯,逻辑或只有有1就为真,全0才是假
例如:1110 & 0011 = 1111 , 1100 & 0011 = 1
3、符号:~
这个叫做按位取反
(3)位取反:位取反符号是~,是将操作数的二进制位逐个按位取反(1变成0,0变成1)
逻辑取反:逻辑取反是符号:!,即真变成假,假变成真。
4、注意:~~和!!
任何非0的数被按逻辑取反再取反就会得到1
任何非0的数被按位取反再取反就会得到自己本身
5、位异或:符号是:^
1^1 = 0 , 0 ^0 = 0, 1^0 = 1 , 0^1 = 1(两个数如果相等结果为0,不等结果为1)
记忆方法:异或就是相异就或操作起来.
总结:
位与:(任何数,其实就是1或者0)与1位与无变化,与0位与变成0.
位或:(任何数,其实就是1或者0)与1位或变成1 ,与0位或无变化。
位异或:(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化。
左移位:<< 与右移位:
>>
C语言的移位要取决于数据类型。
对于无符号数,左移时右侧补0(相当于逻辑移位)
对于无符号数,右移时左侧补0(相当于逻辑移位)
对于有符号数,左移时右侧补0(叫算术移位,相当于逻辑移位)
对于有符号数,右移时左侧补符号位(正书就补0,负数就补1,叫算术移位)
在嵌入式开发中的移位,以及使用的移位属于都是无符号数
注意啦,以下就是应用的重点!!!务必精用!!!!
位与位或位异或在操作寄存器时的特殊作用
清位 , 取反 , 置位
&= ~ ~ |=
例如:我打个比方,在ARM-ContexA9的一个配置寄存器的方法
会了这个,其它的也就类似了!
#define GPIOA *(volatile unsigned int *)0x11000000
Int main(void)
{
//GPIOA &= ~0xf; //将寄存器的低4位清0
// GPIOA |= 0xf ; //将寄存器的低4位置1
//GPIOA &= ~(1 << 4) ; //将寄存器的第4位清0
//GPIOA |= (1 << 4) ; //将寄存器的第4位置1
}