C语言基础一(位运算)

一、程序结构

1、C语言顺序结构

程序是按照从上到下的顺序依次执行的。

2、选择结构

选择结构,程序中会判断并选择一条符合条件的语句执行。

if + else

if(条件表达式)
    执行的语句: 
else if(条件表达式)
    执行的语句;
else
    执行的语句;      

switch case

switch(表达式) //不能为小数,因为计算机中的小数只能存储近似值。
{
    case 常量:
        执行的语句;
        break;
        .
        .
        .
    default:
        执行的语句;
        break;
}

break;是跳出这个选择结构,若是没有break,就继续按顺序结构执行下面的语句。

3、循环结构

for、while、do while。

1、for

for(初始条件(赋值表达式); 条件表达式(终止条件); 步长(循环增量))

循环体;

多条语句必须加花括号。
执行顺序:初, 条, 体, 步。

2、while

while(条件表达式)

循环体;

执行顺序:先判断条表,再执行循环体。

do while

do{
循环体;
}while(条件表达式)
执行顺序: 先执行循环体,在判断条件表达式。

二、位运算

&,|,^,~。
<<,>>。

1、按位与&

真值表:
1 & 1 = 1
0 & 1 = 0
1 & 0 = 0
0 & 0 = 0
注意:位与是&,&&是逻辑与。

2、按位或|

真值表:
1 | 1 = 1
0 | 1 = 1
1 | 0 = 1
0 | 0 = 0
注意:位或是 |,|| 是逻辑或。

3、按位异或^

真值表:
1 ^ 1 = 0
0 ^ 1 = 1
0 ^ 0 = 0
1 ^ 0 = 1
相同的值异或为0,不同的值异或为1。

4、按位取反~

将操作数按照二进制位按位取反(1变成0,0变成1)
注意:按位取反是~,逻辑取反是!

(0或者1) & 0 = 0, (0或者1) & 1 = 其本身;
(0或者1) | 0 = 其本身, (0或者1) | 1 = 1;
(0或者1) ^ 0 = 其本身, (0或者1) ^ 1 = (1或者0,相当于取反);

5、左移位<<、右移位>>

C语言的移位要取决于数据类型,与数据在内存中的存储形式有关。
对于无符号数:
左移<<时,右侧补0(相当于逻辑移位)
右移>>时,左侧补0(相当于逻辑移位)
仅对于无符号数操作,左移动N位,是乘以2的N次方;右移N位,是除以2的N次方
对于有符号数:
左移<<时,右侧补0(算术移位,相当于逻辑移位,符号位会丢失)
右移>>时,左侧补符号位(算术移位,如果正数就补0,负数就补1)

嵌入式中研究、使用的移位都是无符号数。

三、位运算的应用

按位与,按位或,按位异或在操作寄存器时的特殊作用

1、寄存器操作的要求(特定位改变而不影响其他位)

(1)ARM是内存与IO统一编址的,ARM中有很多内部外设,SoC中CPU通过向这些内部外设的寄存器写入一些特定的值来操控这个内部外设,进而操控硬件动作。所以可以说:读写寄存器就是操控硬件。
(2)寄存器的特点是按位进行规划和使用。但是寄存器的读写却是整体32位一起进行的(也就是说你只想修改bit5~bit7是不行的,必须整体32bit全部写入)
(3)寄存器操作要求就是:在设定特定位时不能影响其他位。
(4)如何做到?答案是:读-改-写三部曲。读改写的操作理念,就是:当我想改变一个寄存器中某些特定位时,我不会直接去给他写,我会先读出寄存器整体原来的值,然后在这个基础上修改我想要修改的特定位,再将修改后的值整体写入寄存器。这样达到的效果是:在不影响其他位原来值的情况下,我关心的位的值已经被修改了。

2、特定位清零用&

(任何数,其实就是1或者0)与1按位与时无变化,与0按位与时变成0。
假设原来32位寄存器中的值为:0xAA AA AA AA,要将bit8~bit15清零,可以将这个数与0xFF FF 00 FF按位与,
结果为0xAA AA 00 AA。

3、特定位 置1用|

(任何数,其实就是1或者0)与1按位或变成1,与0按位或无变化。
假设原来32位寄存器中的值为:0xAA A0 00 0A,要将bit8~bit15置1,可以将这个数与0x00 00 FF 00按位或。
结果为0xAA A0 FF 0A。

4、特定位取反用^

(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化。
假设原来32位寄存器中的值为:0xAA AA AA AA,要将bit16~bit23置1,可以将这个数与0x00 FF 00 00按位异或。
结果为0xAA 55 AA AA。

5、用位运算构建特定二进制数

寄存器位操作经常需要特定位给特定值
解法1:直接给出完整的32位特定数。
优势:可以完成工作,难度也不大,操作起来也不是太麻烦。
劣势:依赖工具,而且不直观,读程序的人不容易理解。
评价:凑活能用,但是不好用,应该被更好用的方法替代。
解法2:自己写代码用位操作符号(主要是移位和位取反)来构建这个特定的二进制数

使用移位获取特定位为1,其他位为0的二进制数

如我们需要一个bit3~bit7为1(隐含意思就是其他位全部为0)的二进制数,可以这样:(0x1f << 3)
获取bit3~bit7为1,同时bit23~bit25为1,其余位为0的数:((0x1f << 3) | (7 << 23))

结合位取反获取特定位为0,其他位为0的二进制数

因为移位时是补0的,所以
要获取bit4~bit10为0,其余位全部为1的数,用左移加按位取反的方式来构造比较简单。
首先将构造特定位为1,其他位为0的数,再取反。

如果想要改变的特定位不止一处,那么可以多段分别构造,然后再按位或,这时候的按位或相当于几个数相加。
因为参与位或运算的各个数为1的位是不重复的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值