最近,我在看我同事给我的代码,因为是他自己写的代码,编写规范,易读程度上远不如linux内核源码里面的程序那样容易理解,我分析了主要原因就是里面使用了大量的if-else嵌套,嵌套级数一多脑子就不够用了,因为要时刻记住前面的条件,而且有些变量定义的时候意思比较模糊,因此不容易理解。如下代码timer的中断服务函数所示:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)		/**tim6用于电机转动控制,并且使用了普通更新中断 */
{
	if(htim->Instance == TIM6)//////////////
	{
		if(step_num1 == cur_num1)		/**设置的步进值等于当前值了,说明条件满足了 */
			HAL_TIM_Base_Stop_IT(&htim6);		/**停止中断后,就不会再进入 */
		else		/**条件没满足 */
		{
			if(HAL_GPIO_ReadPin(DET1_GPIO_Port,DET1_Pin)==GPIO_PIN_RESET)		/**0:没检测到光电开关 */
			{	/**心得:if的嵌套相当于两个条件&&运算,都满足才运行代码段 */
				if(step_dir1 == 1)		/**1:离开光电开关,这种情况是允许的,为什么呢?都相当于在中间位置,还希望往回走,或者这么说不允许这种情况,我们希望的是在中间位置,往边上走 */
				{
					HAL_TIM_Base_Stop_IT(&htim6);
					cur_num1 = 0;
					step_err1 = 0;
					step_dir1 = 0;			/**0:好像没有意义,可以理解为其他方向,但是这种情况不存在 */
				}
				else if(step_dir1 == 2)		/**2: 去光电开关方向*/
				{
					cur_num1++;
					step_period1 = SPEED_LOW;
					/**重新计数 */
					HAL_TIM_Base_Stop_IT(&htim6);
					htim6.Init.Period = (uint16_t)step_period1;	/**这里使用了强制类型转换 */
					HAL_TIM_Base_Init(&htim6);
					__HAL_TIM_CLEAR_FLAG(&htim6,TIM_IT_UPDATE);
					HAL_TIM_Base_Start_IT(&htim6);
					HAL_GPIO_TogglePin(PUL_GPIO_Port,PUL_Pin);	/**输出一个方波,定时器6个脉冲引脚搭配,输出方波 */
				}
			}
			else		/**到了边界了 */
			{
				if((step_dir1==1)&&(cur_num1>0))		/**1:离开光电开关方向 */
				{
					cur_num1--;
					if((cur_num1-step_num1>18000)&&(step_period1>SPEED_HIGH))
						step_period1 = step_period1 - 0.01;
					if((cur_num1-step_num1<18000)&&(step_period1< SPEED_LOW))
						step_period1 = step_period1 + 0.01;
				}
				if(step_dir1==2)	/**2:去光电开关方向 */
				{
					cur_num1++;
					if((step_num1-cur_num1>18000)&&(step_period1>SPEED_HIGH))
						step_period1 = step_period1 - 0.01;
					if((step_num1-cur_num1<18000)&&(step_period1< SPEED_LOW))
						step_period1 = step_period1 + 0.01;
				}
				if(step_err1 == 1)
					step_period1 = SPEED_LOW;
				/**重新加载计数值 */
				HAL_TIM_Base_Stop_IT(&htim6);
				htim6.Init.Period = (uint16_t)step_period1;
				HAL_TIM_Base_Init(&htim6);
				__HAL_TIM_CLEAR_FLAG(&htim6,TIM_IT_UPDATE);
				HAL_TIM_Base_Start_IT(&htim6);
				HAL_GPIO_TogglePin(PUL_GPIO_Port,PUL_Pin);		/**输出方波 */
			}
		}
	}
}

        我们不看里面的内容,只看if-else的嵌套级数,前面的主if的嵌套级数为4层,后面主else的嵌套级数为5层,这样写不好,因为级数这么多,有if的条件还比较容易理解,else的条件需要自己在脑子里转换为反逻辑,级数一多,脑子就不够用了。

但是没变法,我最近主要目的是看懂里面的逻辑流程(当满足什么条件的时候需要干什么活),因此我同事写的代码我不会修改,等后面我能力再强一些并且有时间的时候再修改。(根据以前的印象,使用状态机或者内嵌freeRTOS这种实时操作系统是好办法)。

今天主要是讲解这样一个概念,当存在if-else多级嵌套的时候,嵌套的if-else的条件相当于与主if-else的条件做逻辑“&&”的运算,如果更多层的if-else嵌套,相当于逻辑&&的条件累加越来越多,有点向箱现在这个样子:

        if(条件1 && 条件2 && ... 条件n),

        在当前嵌套if的情况,说明前面的若干个条件1,条件2等等是满足的也就是都为true,当前嵌套if条件满足才进入当前的代码段;否则前面n个条件为真,最后条件如果为false,则进入else的代码段。

        值得注意的事,if-else的多级嵌套形成的条件组合呈指数形式递增,有些组合在理论上存在,但是实际没有意义或者根本不可能发生,因此在编写代码过程中往往只关心可能的若干的有限组合的条件。编写对应代码块

(2)if(条件1)-else if(条件2)

        请看以下代码:

void cmd_send(uint8_t* buf_send, uint8_t buf_len)	/**将数组buf_send[buf_len]中的数据打包发出去 */
{
	if(cmd_rx_flag == 0x01)
		CDC_Transmit_FS(buf_send, buf_len);		/**使用USB接口将缓存数组中数据发出去 */
	else if(cmd_rx_flag == 0x02)
		udp_transimit(buf_send, buf_len);		/**使用ETH接口将缓存数组中数据发出去 */
	cmd_rx_flag = 0;		/**消费完了,手动清空标志位 */
}

       里面使用了if(条件1)-else if(条件2),这2种条件判断的语句,并且没有else进行结尾,这种情况相当于if条件反逻辑中一种是我们比较关心的,其他的条件不存在,或者我们不关系,这样就不会有else进行结尾了。这种写法编译器也是允许的,只是看起来像是有漏洞没填补,也就是像是else语句忘了写,这种写法不是很规范,因为如果加上else代码段,但是代码段为空的“;”太浪费代码的空白区域了。比较正规的就是else代码段有一个打印信息提示,linux内核中经常看到使用宏定义定义printf()打印内核信息,有时候这个宏值内容为空的。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐