代码空间优化小结

  • 代码量优化理念
  • 1、合并相同的指令
  • 2、减少相同的函数调用与if条件语句判断
  • 3、逻辑上的优化


代码量优化理念

当我们使用的芯片代码空间大小接近饱和的时但还有功能需要实现的时候就需要缩减代码量,代码量的缩减就好比连连看游戏,将相同的东西抵消,变成一个可重复执行的函数,这样就可以达到节省代码量的效果。代码量的优化也可能会有其他的代价,例如降低代码的可读性和运行效率,这一点是要在优化前进行权衡的。

1、合并相同的指令

优先寻找代码中重复执行的指令,这些重复指令可以封装为函数,通过重复调用同一个函数来达到减少代码量的目的。但这些重复执行的指令不应该不小于跳转函数和退出函数的指令大小,不然就是负优化了。
例子如下:

uint8_t c;

void func(uint8_t a, uint8_t b)
{
	if(1 == a)
		c = 1;
	else if(2 == a)
		c = 2;
	else if(3 == a)
		c = 3;
		
	if(1 == b)
		c = 1;
	else if(2 == b)
		c = 2;
	else if(3 == b)
		c = 3;
}

以上代码可以改为:

uint8_t c;

static void c_init(uint8_t val)
{
	if(1 == val)
		c = 1;
	else if(2 == val)
		c = 2;
	else if(3 == val)
		c = 3;
}

void func(uint8_t a, uint8_t b)
{
	c_init(a);
	c_init(b);
}

2、减少相同的函数调用与if条件语句判断

if-else的条件判断指令也占用了极多的代码空间,调用相同函数但形参不同的函数也可以进行进一步优化。我们可以通过查表的方式来进行优化,将需要改变的值用一个数组储存起来,然后实现与if-else判断中的值相对应,但有可能会降低代码的可读性。
例:

uint8_t a;

void func(uint8_t  c)
{
	if (0 == c)
		a += 3;
	else if(1 == c)
		a += 27;
	else if(2 == c)
		a += 4;
	else if(3 == c)
		a += 8;
}

以上代码可改为

uint8_t a;
code uint8_t num[] = {3, 27, 4, 8};

void func(uint8_t  c)
{
	if(c >= 0 && c < 4)
		a += num[c];
}

当遇到if-else条件不好和对应执行函数对应的情况下,还可以通过一个mask变量来进行优化,如下列伪代码:

void led_onoff(uint8_t led, bool onoff);
void led_func()
{
	if(条件1){
		led_onoff(LED1, 0);
		led_onoff(LED2, 0);
		led_onoff(LED3, 1);
	}else if(条件2){
		led_onoff(LED1, 0);
		led_onoff(LED2, 1);
		led_onoff(LED3, 1);
	}ellse{
		led_onoff(LED1, 1);
		led_onoff(LED2, 0);
		led_onoff(LED3, 1);
	}
}

使用一个mask变量可以在条件判断末尾再进行函数的执行:

void led_onoff(uint8_t led, bool onoff);
void led_func()
{
	uint8_t led_mask = 0;
	if(条件1)
		led_mask = 0x04;
	else if(条件2)
		led_mask = 0x06;
	else
		led_mask = 0x05;
		
	led_onoff(LED1, led_mask & 0x01);
	led_onoff(LED2, led_mask & 0x02);
	led_onoff(LED3, led_mask & 0x04);
}

3、逻辑上的优化

这个放在最后优化,因为这个优化需要理解将要优化的代码的整体功能及逻辑。这个优化最好由代码作者本人进行优化。。。
例:

/* 代码执行效率高,但占空间多 */
	if(a > 0 && b >0)
		c = 0x03;
	else if(a > 0)
		c = 0x02;
	else if(b > 0)
		c = 0x01;

	/* 代码执行效率低,但占空间少 */
	if (a > 0)
		c |= 0x02;
	if(b  > 0)
		c |= 0x01;