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 <stdio.h>
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);
}

浙公网安备 33010602011771号