位运算符

基本概念

原码:正数是其二进制本身;负数是符号位为1,数值部分取X绝对值的二进制

  • 例如:3的原码为 0000 0011;-3的原码为1000 0011

反码:正数的反码是其本身,对于负数其符号位不变其它各位取反(0变1,1变0)。

  • 例如:3的反码为 0000 0011;-3的反码为1111 1100

补码:正数的补码是其本身,负数的补码是其反码的基础上+1。

  • 例如:3的补码为 0000 0011;-3的补码为1111 1101

正数的补码、反码都是其本身

要弄懂位运算符的计算方法,首先必须明白二进制数在内存中的存放形式,二进制数在内存中是以补码的形式存放的。


按位与&

参与运算的两个值,转换成2进制,如果两个相应位均为1时,结果位才为1,否则为0.

例如:8&3,转换成2进制:00001000(8的二进制) & 00000011(3的二进制) 00000000(结果为0)

7 & 3,转换成2进制:00000111(7的二进制) & 00000011(3的二进制) 00000011(结果为3)

-7 & 3,转换成2进制:1000 0111(-7的二进制) & 0000 0011(3的二进制),转换成补码形式1111 1001(-7的补码) & 0000 0011(3的补码), 结果为0000 0001(结果为1)

-7 & -3,转换成2进制:1000 0111(-7的二进制) & 1000 0011(-3的二进制),转换成补码形式1111 1001(-7的补码) & 1111 1101(-3的补码), 结果为1111 1001 这是补码还要转换成原码,转换后为 1000 0111(结果为-7)


按位或 |

参与运算的两个值,转换成二进制,如果两个数的相应位有1,结果位就为1。

例如:8&3,转换成2进制:00001000(8的二进制) | 00000011(3的二进制) 00001011(结果为11)

7 & 3,转换成2进制:00000111(7的二进制) | 00000011(3的二进制) 00000111(结果为7)

-7 & 3,转换成2进制:1000 0111(-7的二进制) | 0000 0011(3的二进制),转换成补码形式1111 1001(-7的补码) | 0000 0011(3的补码), 结果为1111 1011这是补码,转换成原码为1000 0101(结果为-5)

-7 & -3,转换成2进制:1000 0111(-7的二进制) | 1000 0011(-3的二进制),转换成补码形式1111 1001(-7的补码) | 1111 1101(-3的补码), 结果为1111 1101这是补码,转换成原码为1000 0011(结果为-3)


按位异或 ^

参与运算的两个值,转换成二进制,如果两个数的相应为相同,为0,否则为1.

例如:8&3,转换成2进制:00001000(8的二进制) ^ 00000011(3的二进制) 00001011(结果为11)

7 & 3,转换成2进制:00000111(7的二进制) ^ 00000011(3的二进制) 00000100(结果为4)

-7 & 3,转换成2进制:1000 0111(-7的二进制) ^ 0000 0011(3的二进制),转换成补码形式1111 1001(-7的补码) ^ 0000 0011(3的补码), 结果为1111 1010这是补码,转换成原码为1000 0110(结果为-6)

-7 & -3,转换成2进制:1000 0111(-7的二进制) ^ 1000 0011(-3的二进制),转换成补码形式1111 1001(-7的补码) ^ 1111 1101(-3的补码), 计算结果为0000 0100,十进制为 4


按位取反运算符 ~

取反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。

例如:~7,转换成2进制:0000 0111(7的二进制)[原],求补码0000 0111 [补],对补码取反,包括符号位1111 1000,最后补码转原码1111 0111 [反码],1000 1000 [原码]

计算步骤:

  1. 先对正数求补码
  2. 然后对补码取反,包括符号位
  3. 最后进行一个补码求原码的过程

快速计算小技巧:

  1. 所有正整数的按位取反是其本身+1的负数

  2. 所有负整数的按位取反是其本身+1的绝对值

  3. 零的按位取反是 -1(0在数学界既不是正数也不是负数)


左移(<<)、右移(>>)运算符

左移运算符和右移运算符都是双目运算符。

左移运算:其功能是将运算符‘<<’左边的操作数的各二进制位全部左移指定的位数。左移时,操作数移出左边界的位被屏蔽,从右边开始用0填补空位,其表达式的一般形式为:(操作数) << (移位位数)

例如:13 << 3, 将操作数转换成二进制0000 1101,左移3位0110 1000,十进制就是104。

15<<2, 将操作数转换成二进制0000 1111,左移2位0011 1100,十进制就是60。

计算技巧: (操作数) x 2移位位数 ,例如:13 x 23 = 104, 15 x 22 =60。

右移运算:其功能是将运算符‘>>’ 左边的操作数的各二进制位全部右移指定的位数。

右移时,操作数移出右边的位被屏蔽,从左边开始用符号位填补空位。如果原先最高位是1,则填补1;如果是0,则填补0,其表达式的一般形式为:(操作数) >> (移位位数)

例如:16 >> 3, 将操作数转换成二进制0001 0000,右移3位0000 0010,十进制就是2。

15>>2, 将操作数转换成二进制0000 1111,右移2位0000 0011,十进制就是3。

-15>>2, 将操作数转换成二进制1000 1111,转换成补码 1111 0001,右移2位1111 1100,转换成原码1000 0100十进制就是-4。

&lt;think&gt;好的,用户的问题是关于单片机中的&ldquo;三位运算符&rdquo;的使用说明或示例。首先,我需要确认用户是否指的是&ldquo;三目运算符&rdquo;或者是否存在其他可能的误解。因为在编程中,常见的位运算符通常是按位与(&amp;)、按位或(|)、按位异或(^)、按位取反(~)、左移(&lt;&lt;)和右移(&gt;&gt;),这些通常被称为位运算符,而&ldquo;三位运算符&rdquo;这个术语并不常见,可能是用户输入时的笔误。 接下来,我会考虑用户提到的参考引用内容,其中提到了位运算符的种类,如左移、右移、按位取反等。用户可能将&ldquo;三目运算符&rdquo;误写为&ldquo;三位运算符&rdquo;,或者可能是指三个位的操作。但根据常见的编程知识,三目运算符(条件运算符)是存在的,形式为条件 ? 表达式1 : 表达式2,用于条件判断。而位运算符中并没有三位的运算符,因此需要进一步澄清。 然后,我需要检查单片机编程中常用的运算符。在C语言中,单片机常用的位运算符是上述提到的那些,每个运算符处理的是单个位或多个位的组合。例如,按位与用于屏蔽某些位,按位或用于设置某些位,移位运算用于乘以或除以2的幂次方。用户可能想了解如何使用这些位运算符进行三位的操作,比如同时操作三个位,或者处理三位的数据。 另外,用户可能是在问三目运算符在单片机中的应用,比如条件判断的简洁写法。但根据用户的引用内容,他们之前的问题是关于位运算符的,所以更可能是在询问位运算符相关的三位操作。例如,如何用位运算符提取或设置三个连续的位。 考虑到用户可能的混淆,回答中需要先澄清可能的术语误解,然后分别解释三目运算符和位运算符中的三位操作。同时,需要提供具体的示例代码,说明在单片机编程中如何应用这些运算符,比如寄存器操作中的位掩码设置、状态标志的读取或修改等。 最后,生成相关问题,帮助用户进一步理解相关概念,比如三目运算符与if语句的区别、位运算优化技巧等。&lt;/think&gt;[系统级回答] 关于单片机编程中&quot;三位运算符&quot;的说明如下: 1. 术语澄清: &quot;三位运算符&quot;实际为术语混淆,可能指以下两种运算符: - 三目运算符(条件运算符):唯一的三操作数运算符$条件 ? 真值表达式 : 假值表达式$ - 位运算符:处理二进制位的运算符,如$&amp;, |, ^, ~, &lt;&lt;, &gt;&gt;$等[^1] 2. 三目运算符示例: ```c // 设置GPIO输出电平 GPIO_PIN = (电压 &gt; 2.5V) ? HIGH : LOW; // 计算PWM占空比 uint8_t duty_cycle = (温度 &gt; 30) ? 75 : 50; ``` 3. 位运算符的三位操作: ```c // 定义3位状态寄存器(假设使用低3位) #define STATE_MASK 0x07 // 二进制00000111 // 设置后三位状态 PORT |= (new_state &amp; STATE_MASK); // 保留其他位,设置低3位 // 读取中间三位(假设位3-5) uint8_t sensor_val = (ADC_DATA &gt;&gt; 3) &amp; 0x07; // 三位置换操作 value = (value &amp; 0xF8) | (new_bits &amp; 0x07); // 保持高5位不变,替换低3位 ``` 4. 复合位运算示例: ```c // LED阵列控制(假设每3位控制一组RGB LED) uint32_t led_ctrl = 0; led_ctrl |= (red &lt;&lt; 0) | (green &lt;&lt; 1) | (blue &lt;&lt; 2); // 设置第一组颜色 led_ctrl |= (模式 ? 0x38 : 0x07) &lt;&lt; 3; // 根据模式设置第二组颜色 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值