以下文章来源于:公_众_号开源电子网 读取更多技术文章,请扫码关注 虽然C语言基础知识很简单,但是如果我们不学习C语言高级玩法,那么我们还是入门级的程序员,例如一个功能自己使用100行实现,到处if else语句等等,别人50行代码完成功能实现,代码格式还那么精简,对于企业来讲,精简的代码有利于维护以及查找bug简单,如果我们不优化自己的代码,那么后期维护性是非常吃力的。
本节课,我们使用计数前导零_CLZ(x)来制作一个管理事件代码,计数前导零有两种方法,一种计算高位最高优先级的事件,第二种计算最低优先级的事件。
前导置零方法:计数前导零是对位列表的一种操作,它从最高有效位开始计算第一个位之前存在多少个零位,对于C语言的unsigned int 一般是32位的,例如0000 0000 0000 0000 0000 0000 0000 0000的32位,如果我们计算 unsigned int x = 0x5fffffff使用_CLZ(x)计算前导零为1,如图所示:
因为0x5fffffff转成二进制位0101 1111 1111 1111 1111 1111 1111 1111,而最高位的零的个数为1个,所以_CLZ(x)计算前导零为1,这个前导零一般在FreeRTOS操作系统的RTOS就绪链表查找最高优先级,数值越高,优先级越高, 从上述图可知,我们可不可以从最低位查找0的个数,那么我们先分析问题: 1,首先我们把低位和高位替换位置,例如0x5ffffff1转成0x1ffffff5。
2,然后我们进行CLZ计数前导零,从上图可知,计算得出为3。 实现源码: 前面我们一讲讲解了两步奏,先低位替换成高位,然后使用CLZ计数前导零,如以下源码所示:
__asm int os_ffs(int value)
{
CMP R0, #0x00 /* R0是否为0 */
BEQ exit
RBIT R0, R0 /* 低位和高位替换 */
CLZ R0, R0 /* 计算前导零指令 */
exit
BX LR /* R0为0返回 */
}
第三行CMP R0, #0x00主要判断R0(value)是否为零,如果为零则运行exit以后的代码,然后调用RBIT R0, R0 /* 低位和高位替换 */,最后计算前导零指令。
应用场景:方法1: 我们使用LVGL为例,如果我们制作一个图标的界面,我们不可能每个图标使用一个回调函数,这样造成代码量太大,无法做到精简,那么我们就让他们共用一个回调函数,那么我们怎么区分它们那个触发了事件了呢,这个是一个重点的问题,那么小编是这样写的,如以下源码所示: 1,定义一个32位的obj_readly_list变量,如果数据结构学习不错的,也可以使用链表形式。 2,当我们按下某一个图标时,那么我们触发某个事件,例如该图标人为设定事件1,那么obj_readly_list就等于0x00000002(对应以下代码的第一步) 3,这个变量lv_bit = (31UL - ( unsigned char )__clz( ( obj_readly_list ) ) );(对应第二步)计算前导置零得出31-__clz(0x00000002) = 31 – 30 = 1,那么表示事件1被触发了,然后对obj_readly_list清零操作(对应第三步)。 4,最后我们switch case语句进行判断事件1(lv_bit为1)对应的动作。
void lv_event_cb(lv_event_t *event)
{
lv_event_code_t code = lv_event_get_code(event);
lv_obj_t * obj = lv_event_get_target(event);
if (code == LV_EVENT_CLICKED)
{
for (int i = 0;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?