位操作简介
运算符 | 含义 | 运算符 | 含义 |
---|---|---|---|
& | 按位与 | ~ | 取反 |
| | 按位或 | << | 左移 |
^ | 按位异或 | >> | 右移 |
运算符 | 含义 |
---|---|
&按位与 | 有0则0,全1为1 |
|按位或 | 有1则1,全0为0 |
^按位异或 | 相同为0,不同为1 |
对于二进制位操作,与1进行&操作,就是本身,与0进行|操作也是本身
故对某一位清零,一般使用&操作,对某位赋1,用|操作
对寄存器的某一位(bit)赋1,可以用以下操作
TEST |= 1 << bit;
同样的,对某一位清零,可以这样写
TEST &= ~(1 << bit);
嵌入式32中位操作的用法
一个32bit数据的位,字节读取操作
- 获取单个字节
#define GET_LOWBYTE0(x) ((x >> 0) & 0X000000FF) //与1进行&操作就是本身
#define GET_LOWBYTE1(x) ((x >> 8) & 0X000000FF)
#define GET_LOWBYTE2(x) ((x >> 16) & 0X000000FF)
#define GET_LOWBYTE3(x) ((x >> 24) & 0X000000FF)
例:
#include <stdio.h>
#define GET_LOWBYTE0(x) ((x >> 0) & 0X000000FF) //与1进行&操作就是本身
#define GET_LOWBYTE1(x) ((x >> 8) & 0X000000FF)
#define GET_LOWBYTE2(x) ((x >> 16) & 0X000000FF)
#define GET_LOWBYTE3(x) ((x >> 24) & 0X000000FF)
int main()
{
unsigned int a = 0x12345678;
printf("0x%x第0个字节是:0x%x\n", a, GET_LOWBYTE0(a));
printf("0x%x第1个字节是:0x%x\n", a, GET_LOWBYTE1(a));
printf("0x%x第2个字节是:0x%x\n", a, GET_LOWBYTE2(a));
printf("0x%x第3个字节是:0x%x\n", a, GET_LOWBYTE3(a));
return 0;
}
输出结果是:
- 获取某一位
#define GET_BIT(x,bit) ((x & (1 << bit)) >> bit) //让x的第bit位与1进行&操作,再把这一位右移bit位,这样结果就是这个位本身了
例:
#include <stdio.h>
#define GET_BIT(x,bit) ((x & (1 << bit)) >> bit)
int main()
{
unsigned int a = 0x68; /*二进制01101000*/
int i;
for ( i = 0; i < 8; i++)
{
printf("0x%x第%d位是:%d\n", a, i , GET_BIT(a,i));
}
return 0;
}
结果:
一个32bit数据的位,字节清零操作
- 清零某个字节
#define CLEAR_LOW_BYTE0(x) (x &= 0xffffff00) /*与0进行&操作,清零第0个字节*/
#define CLEAR_LOW_BYTE1(x) (x &= 0xffff00ff) /* 清零第1个字节 */
#define CLEAR_LOW_BYTE2(x) (x &= 0xff00ffff) /* 清零第2个字节 */
#define CLEAR_LOW_BYTE3(x) (x &= 0x00ffffff) /* 清零第3个字节 */
例:
#include <stdio.h>
#define CLEAR_LOW_BYTE0(x) (x &= 0xffffff00) /*与0进行&操作,清零第0个字节*/
#define CLEAR_LOW_BYTE1(x) (x &= 0xffff00ff) /* 清零第1个字节 */
#define CLEAR_LOW_BYTE2(x) (x &= 0xff00ffff) /* 清零第2个字节 */
#define CLEAR_LOW_BYTE3(x) (x &= 0x00ffffff) /* 清零第3个字节 */
int main()
{
unsigned int a = 0x12345678;
unsigned int b = 0x12345678;
unsigned int c = 0x12345678;
unsigned int d = 0x12345678;
printf("0x12345678的第0个字节清零后是: %#.8x\n",CLEAR_LOW_BYTE0(a));
printf("0x12345678的第1个字节清零后是: %#.8x\n",CLEAR_LOW_BYTE1(b));
printf("0x12345678的第2个字节清零后是: %#.8x\n",CLEAR_LOW_BYTE2(c));
printf("0x12345678的第3个字节清零后是: %#.8x\n",CLEAR_LOW_BYTE3(d));
return 0;
}
结果:
- 清零某一位
#define CLEAR_BIT(x,bit) (x &= ~ (1 << bit) ) /*清零bit位*/
例:
#include <stdio.h>
#include <stdlib.h>
#define CLEAR_BIT(x,bit) (x &= ~(1 << bit))
int main()
{
unsigned int a = 0b11111111;
char string[32] = {0};
int i;
for ( i = 0; i < 8; i++)
{
CLEAR_BIT(a,i);
itoa(a, string, 2); //利用itoa函数,把数据转成2进制的字符串
printf("清零第%d位后为:%s\r\n",i,string);
a = 0b11111111;
}
return 0;
}
结果:
一个32bit数据的位,字节置1操作
- 置某个字节为1
#define SET_LOW_BYTE0(x) (x |= 0x000000ff) /* 第0个字节置1 */
#define SET_LOW_BYTE1(x) (x |= 0x0000ff00) /* 第1个字节置1 */
#define SET_LOW_BYTE2(x) (x |= 0x00ff0000) /* 第2个字节置1 */
#define SET_LOW_BYTE3(x) (x |= 0xff000000) /* 第3个字节置1 */
例:
#include <stdio.h>
#define SET_LOW_BYTE0(x) (x |= 0x000000ff) /* 第0个字节置1 */
#define SET_LOW_BYTE1(x) (x |= 0x0000ff00) /* 第1个字节置1 */
#define SET_LOW_BYTE2(x) (x |= 0x00ff0000) /* 第2个字节置1 */
#define SET_LOW_BYTE3(x) (x |= 0xff000000) /* 第3个字节置1 */
int main()
{
unsigned int a = 0x12345678;
unsigned int b = 0x12345678;
unsigned int c = 0x12345678;
unsigned int d = 0x12345678;
printf("0x12345678的第0个字节置1后是: %#.8x\n",SET_LOW_BYTE0(a));
printf("0x12345678的第1个字节置1后是: %#.8x\n",SET_LOW_BYTE1(b));
printf("0x12345678的第2个字节置1后是: %#.8x\n",SET_LOW_BYTE2(c));
printf("0x12345678的第3个字节置1后是: %#.8x\n",SET_LOW_BYTE3(d));
return 0;
}
结果:
- 置位某一位
#define SET_BIT(x,bit) (x |= (1 << bit)) /*置位第bit位*/
例:
#include <stdio.h>
#include <stdlib.h>
#define SET_BIT(x,bit) (x |= (1 << bit)) /*置位第bit位*/
int main()
{
unsigned int a = 0b00000000;
char string[32] = {0};
int i;
for ( i = 0; i < 8; i++)
{
SET_BIT(a,i);
itoa(a, string, 2); //利用itoa函数,把数据转成2进制的字符串
printf("置1第%d位后为:%s\r\n",i,string);
a = 0b00000000;
}
return 0;
}
结果: