while(i--)陷阱

1.案例

  在访问一段存储空间时使用到“while(i–)”模型代码,抽出主体代码。

/**
  * @brief  获取数据
  * @param  buf:数据返回地址
  			size:数据长度
  * @retval 实际获取的数据长度
*/
uint32_t read_buf(uint8_t *buf,uint32_t size)
{
	uint32_t temp = 0;
	uint8_t	 data = 0;
	
	temp = size;
	
	while(temp--)
	{
		if(get_byte(&data))		/*从某一地址读取1字节数据,成功返回1 */
		{
			*buf++ = data;
		}
		else
		{
			break;	
		}
	}
	return (size-temp);
}

2.分析

【1】while(i–)语句执行顺序:
 ●判断i是否大于0,然后执行“i–”;“i–”语句不论前面条件是否满足都会执行,因此导致问题出现;
 ●条件“1”成立则执行while循环里面语句。

写个测试例子:

#include 

int main(void)
{
	int i = 4;
   	while(i--)
  	 {
   		;
  	 }
  	 printf("i=%d\n",i);
   
   	return 0;
}

输出结果:i=-1
在这里插入图片描述
【2】存储空间的数据大于等于读取数据(size)时,导致temp自减越界,为负数(有符号数)或者最大值(无符号数);

【3】存储空间的数据小于读取数据(size),导致“多访问”1字节的假象;

  举个例子:假设存储空间中只有5个字节数据,现在调用该函数读取10字节数据;函数期望的值当然是返回实际读出的5字节数据及长度5。

  函数通过temp变量记录访问数据长度;当访问到第5字节后,跳出while循环;根据“【1】”分析,语句“temp–”不管while的判断条件,直接先执行;此时,会误认为多访问1字节数据,即函数返回值为6。


3.修改

  变量变化确保随关联条件变化而变化。代码应尽量避免语句执行顺序歧义、模糊逻辑,方便用户阅读。

/**
  * @brief  获取数据
  * @param  buf:数据返回地址
  			size:数据长度
  * @retval 实际获取的数据长度
*/
uint32_t read_buf(uint8_t *buf,uint32_t size)
{
	uint32_t temp = 0;
	uint8_t	 data = 0;
	
	temp = size;
	
	while(temp)
	{
		if(get_byte(&data))		/*从某一地址读取1字节数据,成功返回1 */
		{
			*buf++ = data;
			temp--;
		}
		else
		{
			break;
		}
	}
	return (size-temp);
}

你可能感兴趣的:(C,C++,bug汇总)