1、算术操作运算
2、逻辑运算
3、位运算
4、赋值运算
5、内存访问符号
1、算术操作运算
- -:左右两边的值都属于同种数据类型,尽量两边的数据类型是一致的。
、/、%:,
、/:我们大部分的cpu都是不支持的,很多时候看到乘法,没有办法找到一个汇编层进行乘法的。
Int a = b * 10;很多时候如果cpu功能很强大,可以用多个周期调用实现,但是效率很低,甚至要利用软件模拟方法去实现乘法,很多时候这个乘法会被编译器编译成软件乘法的方法去调用系统函数,如果写的是裸机的程序,没有操作系统的时候第三方库的支持的时候,纯粹是自己的库在开发的时候就实现不了,我们需要第三方的乘法库来帮我们实现,这样对我们嵌入式纯软来说效率会特别的差。所以说、/法除非特别要求外,能不用就不用,因为、/不支持,会导致我们CPU的可移植性变差。
Int a = b + 10;cpu一个周期就可以实现,效率非常的高
%:求模,求余数
0 % 3 = 0 1 % 3 = 1 2%3 = 2 3%3 = 0 4%3 = 1,求模的数比如m,它的结果一定是0到m-1
n % m = res[0 – m-1]
取一个范围的书
比如给我们一个任意数(随机数),我们只想得到1-100以内的数,这个时候就可以利用求模
(m%100) + 1 ==>res
得到一个m进制的一个个位数,
循环数据结构的下标
比如想知道这个栈的下标可以利用求模来实现
2、逻辑运算
逻辑运算:选择就是真与假,返回结果就是1和0,本来在C语言中就是用1来代表真,0来代表假,后来优化了,我们看到0就是假,我们看到非0就是真,具体的位运算符号如下。
||、&&
A||B:A和B只要有一个为真,这个就是真 === B||B 这两个是不等于的
这里需要注意的是如果A为真B就不执行了,A不为真是B才执行,所以这两个交换是有区别的,简单的来说就是C语言编译器看到A已经为真了,就没有执行B的必要了。A&&B也是一样的,如果A已经是为假了B也就不执行了,C语言编译器会进行一个预判断,看看要不要执行B
# include <stdio.h> int main(void) {
int a = 10; int res; res = (a==10) || (printf("hello,world\n")); printf("the res is %d\n", res); return 0; }
输出结果为:
如果a != 10,输出结果为
A&&B:A或者B两个同时为真,才为真。
>、>=、<<=
根据我们所理解的数学概念,比较大小
!
取反的意思,原来为真,加这个就是假
对比位运算中的取反 int a = 0x0,取反~a0Xfff;这个是每一位都进行取反,数值取反,而不是结果取反,这两个的概念是不一样的。
? :
典型的if else的感觉,一般情况只要知道if else都是可以看懂的。
3、位运算
位运算是最接近底层的开发,最接近于硬件开发的一组操作符号,位运算的应用频率是非常的高的,这里一定要把位运算什么时候用,用到技巧一定要能掌握得到,主要有以下的分类。
1)移位符号:<<、>>
2)&、|、^
3)^、~
1)移位符号:<<、>>
<<:这个是二进制的左移,相当于 乘以2,因为这里是指二进制的左移和右移
m<<1; m2
m<<n; m2^n
4: 用二进制来表示是00100
8:用二进制表示是01000
乘法一般不建议使用,但是如果是2的倍数,用左移来实现是比较好的,c语言编译器会帮助我们实现这个的。举例子:int a = b *32,这个样子c语言并不会直接调用软件乘法的代码或者乘法库来实现,而是自动转换为====>b<<5,这样子CPU一个周期就可以把这个代码运算完
[数据、数字]
-1 *2 -2
8 bit:第一个位置,1来表示负数,0来表示整数
-1 :
源码:1 0 0 0 0 0 0 1
取反:1 1 1 1 1 1 1 0
补码:1 1 1 1 1 1 1 1(符号位不变,其他位置取反,后加1就是我们在计算机内部表示的事情)
-1在计算机中真实的表示就是8个全1,这个在计算机中会被当做一个特殊的状态,全部高电频。
-2
源码:1 0 0 0 0 0 1 0
取反:1 1 1 1 1 1 0 1
补码:1 1 1 1 1 1 1 0
-1 和 -2相当于左移了一位,有空位产生,左移同意用零来补,所以我们左移都可以用乘以2的关系,无论是正数还是负数。
<<:右移统一像右移动一个位置,这个时候肯定空出了一个位置,那这里是填0好尼,还是按照最高位置来填1比较好,这里是跟符号变量有关。
右移:除以2
Int a;a >>n
m >> n m/2^n
有符号数右移填如果是负数填1,正数填0,这是右移的逻辑性。
Unsigned int a a>>n
这两个数字在内存中的表现形式是完全不一致的,右移符号是一个完全遵守符号位的变量操作符
Int a = XXX;//如果a是正数正常输出======,如果a是负数,则会出现死循环,因为负数的//最高位都是用1来补的,这里这段内存空间永远不能全部被0占用,因为始终有占位符1
While (a){
a = a>>1; } Printf(“=========\n”); 当a是正数 # include<stdio.h> int main(void) {
int a = 10; while(a){
a = a>>1; } printf("=======\n"); return 0; } ```输出结果为: ![在这里插入图片描述](https://img-blog.csdnimg.cn/.png) 如果a = -10 ```c # include<stdio.h> int main(void) {
int a = -10;//默认为有符号数。 while(a){
a = a>>1; } printf("=======\n"); return 0; }
输出结果为:
2) &、|、^
数字电路会比较熟悉,硬件中会有与门、非门、异或非们一些基本数字逻辑操作,跟我们软件很像,也是完成一些足位取位,足位屏蔽位置的关系。
&:与
A&0 —>0,任意一位与上0的一定是0,这个样子就详相当于把其他位欸屏蔽掉了。
1)屏蔽
Int a = 0x1234;
a & 0xff00这个操作下来其实就是屏蔽低8位,取出高8位(开发中和硬件打交道会用的多)
A & A1—> A取出,
清零器clr
|:或
A | 0 ====A
保留
A | 1 ===1
设置为高电平的方法,设置为set
^:异或
设置一个资源的bit5为高电平,这里有一个不成文的规定,bit5是从左往右的第六个个职位,因为bit是从0开始计数的,这里是从左往右边进行数的。
Int a;
a = a | 10000,这个样子写没有问题,但是需要自己去做,所以我们更希望计算去做
a = (a | (0x1<<5)),我们更倾向于这个样子去写 ===>我们可以去扩展为a = (a | (0x1<<n)),将bitn设置为高电平
清除bit5
a = a & 011111:这里相当于31,但是这里是很有风险的,因为这里只是占用了31个位置,只有后5位是1,其他的高位为0,如果进行了与操作,a的高位也会变成0,这样子CPU在执行的时候就会出错。
a = a &(~ (0x1<<5)) ==> a &(~ (0x1<<n))对某一个位置进行清零,底层驱动和嵌入式开发中一定会用到。
4、 ^、~
1 ^ 1= 0 0 ^ 0 = 0:硬件上的表达不是很多,但是在算法上的应用会很多,进行加密或者解密,用异或处理逻辑的情况会很少,但是数学家用的算法会比较的多。
小技巧:交换两个数
Int fun() {
Int a = 20; Int b =30; a = a ^ b; b = b ^ a; a = a ^ b; }
~:足位取反
0xf0 ~ 0xffff ff0f
我们想把一个资源456设置为101?
4、赋值运算
1)=
2)+=、-=、&=、……符合运算
a | (0x1<<5) ~a这里a的值是不变的,这里的变量没有自更新能力
a = a + b 等价于a += b,等号就是赋值运算
a | = (0x1<<5)
a &= ~(0x1<<5)
5、内存访问符号
1)()
2)[]
3){}
4)->、.
5)&、*
1)()
限制符:(a+b) * c
函数访问符号:int fun();
2)[]:数组,内存访问的ID符号
3){}:函数体的限制符:struct abc{xxxxx}
4)->、.:变量访问
5)&、*:&都是数字是位运算,*就是取地址,*p就是取地址,都是数字的话都是乘法。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/101316.html