用函数替换重复的代码行

时间:2014-05-08 10:44:37

标签: c optimization refactoring embedded readability

我在嵌入式C上工作,我正在尝试重构代码以提高可读性并优化我项目中使用的ROM。

我在切换案例中多次重复这3行代码,以更新特定屏幕名称上的特定编辑框。

EbSetText和SetState是预定义的图形库函数。

sprintf(Screen1_Editbox1_Text,"%04d",GetHV(0));
EbSetText((EDITBOX *)GOLFindObject(ID_Screen1_Editbox1), Screen1_Editbox1_Text);
SetState(GOLFindObject(ID_TestProbe_HVEb01), EB_DRAW);

有些代码重复如下:

EbSetText((EDITBOX *)GOLFindObject(ID_Screen1_Editbox1), "Text to output");
SetState(GOLFindObject(ID_TestProbe_HVEb01), EB_DRAW);

对于各种文本框和字符串/缓冲区输入,上面的代码重复120次。主要是我的代码的可读性受损,我接近我的ROM的90%。

我正在考虑用实用程序函数替换它以包含所有上述逻辑。

SetTextofEditBox(Screen1_Editbox1_Text,ID_Screen1_Editbox1);

用单一效用函数替换它会在这里有什么好处吗?

2 个答案:

答案 0 :(得分:2)

正如unwind所说:函数调用可能比现在更昂贵。当然,笨重的函数和重复相同的代码会导致代码难看,因此难以维护,因此更容易出错。

我个人考虑使用inline函数,让编译器决定代码是否应该在本地执行,或者函数调用确实是更好的选择。
或者,如果你愿意,你也可以简单地使用一个宏。

inline通常被认为是更好的选择,看一下你发布的那些小代码片段,我说你也应该在这里寻找内联函数。
请记住,inline将它留给编译器来决定函数是否将被内联,所以如果 - 在一些严肃的,有代表性的测试之后 - 你觉得函数应该总是内联,并且您正在使用gcc,您可以使用GCC always_inline属性:

__attribute__((always_inline)) void your_inline_func(void *x, const char *y){}

如果不能说服你的编译器总是如此容易地内联函数,那么你将不得不恢复使用宏。请注意:宏不是类型安全的,并且可能有副作用:必须进行彻底的测试。

根据您发布的两个声明,一种使您的代码更加"数据驱动" 的方法,正如展开建议的那样:

const char *txt_argument;
//and for any other argument you might need, too:
EDITBOX *edit = NULL;
//possibly add SetState's  arguments
switch(foo)
{
    case bar:
        txt_argument = Screen1_Editbox1_Text;
        edit = (EDITBOX *)GOLFindObject(ID_Screen1_Editbox1);
        break;
    case zar:
        txt_argument = "Text to output";
        edit = (EDITBOX *)GOLFindObject(another_editbox);
        break;
}
EbSetText(edit, txt_argument);

这并没有真正减少你拥有的代码量,但确实可以更容易地监督switch实际上在做什么。

如果您正在研究(进一步)优化这一大switch语句的方法,那么您可以查看nesting the switch cases。很可能这几乎没有任何影响,但对于某些编译器,在某些情况下,它可以有所作为。

如果你有120个病例,试着看看你是否可以将它们分成2组或3组:非常常见的那些,可能的那些,以及那些很少发生的病例。最常见的情况是主switch,然后default包含另一个列出不常见情况的开关,反过来,默认情况下是处理罕见情况的开关。登记/> 嵌套当然容易出现代码混乱,如果您愿意,可以使用一系列较短的default: switch替换switch位,然后返回...

答案 1 :(得分:0)

也许。很难说,这取决于额外函数调用的开销是否大于本地工作的开销。

您可以尝试将其分解并进行更多数据驱动",即安排代码,以便始终调用EbSetText()SetState()函数switch,但要将参数设置为每个case正确设置的变量。