我在嵌入式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);
用单一效用函数替换它会在这里有什么好处吗?
答案 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
正确设置的变量。