2014-05-08 2 views
1

Я работаю над встроенным C и пытаюсь переформулировать код, чтобы улучшить читаемость и оптимизировать ПЗУ, используемые в моем проекте.Замена повторяющихся строк кода функцией

У меня эти три строки кода повторяются много раз в коммутационных шкафах, чтобы обновить конкретное окно редактирования на конкретном имени экрана.

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 раз для различных текстовых окон и строк/входов буфера present.It болит читаемость моего кода, главным образом, и я приближаясь к 90% моего ПЗУ.

Я думаю о замене его функцией полезности, чтобы содержать все вышеперечисленную логику.

SetTextofEditBox(Screen1_Editbox1_Text,ID_Screen1_Editbox1); 

Заменяет ли его единственная функция полезности здесь?

+0

Может ли Macro быть полезной для вашей цели. –

ответ

2

Как можно сказать: возможно, что вызов функции окажется дороже, чем у вас сейчас. Конечно, громоздкие функции и повторение одного и того же кода делают для уродливого кода, который сложнее поддерживать и в результате: больше подвержено ошибкам.

Я лично рассмотрел возможность использования функции inline, и пусть компилятор решит, должен ли код выполняться локально, или вызов функции действительно является лучшим вариантом.
Или, если хотите, вы могли бы просто использовать макрос.

inline, как правило, считается лучшим вариантом, и, глядя на эти крошечные фрагменты кода, которые вы отправили, я бы сказал, что вы, вероятно, должны пойти на встроенные функции здесь.
Помните, что inline оставляет его компилятору, чтобы решить, будет ли эта функция встроена или нет, поэтому, если после какого-то серьезного и репрезентативного тестирования вы чувствуете, что функция должна всегда быть встроенной, и вы с помощью GCC, вы можете использовать атрибут GCC always_inline:

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

Если ваш компилятор не может быть уговорили всегда встраивать функцию так легко, то вам придется вернуться к использованию макроса. Будьте внимательны: макрос не является безопасным по типу и может иметь побочные эффекты: тщательное тестирование является обязательным.

На основании 2 заявления вы размещены, один из способов сделать код более «данные-драйв» как размотки может быть предложено следующее:

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 -es, с последующим возвращением ...

+0

Встраиваемые компиляторы обычно любят выполнять много инкрустаций, поэтому это хорошее решение. – Lundin

+0

@ Lundin: ну, как всегда: вы не можете реально быть на 100% уверенным, если вы, конечно же, не попробуете «n тест», но, конечно, имеет смысл для встроенной разработки, чтобы поддержать inlining, наверняка –

0

Возможно. Трудно сказать наверняка, это зависит от того, будет ли накладные расходы на дополнительный вызов функции выше, чем накладные расходы на выполнение работы локально.

Вы могли бы попытаться разбить его, и сделать его немного более «управляемый данными», т.е. организовать код так, чтобы EbSetText() и SetState() функции всегда вызываются после switch, но сделать свои аргументы в переменные, которые установлены правильно каждым case.

+0

Хорошая идея, но у меня есть много условий, если внутри корпуса коммутатора. – Gopi

+0

@Gopi Fine ... но почему вы приняли ответ, который реализует это? :) – unwind

+0

Могу ли я принять ваши тоже :)? Я хотел дать upvote, но у меня нет репутации, чтобы сделать это :( – Gopi

Смежные вопросы