|
Два входа в одну функцию на C, возможно ли такое? |
|
|
|
 |
Ответов
(1 - 47)
|
Dec 2 2010, 11:43
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Код void Indication(void) { ... }
void Control(void) { ... }
void Combo(void) { Control(); Indication(); } Без комментариев. The Best
|
|
|
|
|
Dec 2 2010, 11:47
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(ViKo @ Dec 2 2010, 14:28)  Можно ли так сделать на C? Иметь в середине функции метку, и вызвать функцию по указателю на эту метку? Можно, но не так. Сделать внутри switch(), а переключатель передавать снаружи. Если тупо перейти по метке, то при операции RET произойдёт возврат хз куда, но не туда, куда нужно. И вообще, пролог, эпилог - это всё нельзя пропускать.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Dec 2 2010, 11:57
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Имеется некоторая избыточность в виде лишнего вызова От лишнего вызова можно избавится поигравшись с компилятором (я не знаю какой он у вас, и какой проц, от этого многое зависит), попробовать функции объявить inlinе и .т.д. Но то что вы хотите сделать это гомнокод еще тот, даже и не думайте о таких подходах. В самом крайнем случае заменить функции дефайнами, и то прравельней будет. Код #define Indication() \ {\ ...\ }\
#define Control()\ {\ ...\ }\
void Combo(void) //и никакого оверхеда только можно таких багов нахвататься { Control(); Indication(); }
|
|
|
|
|
Dec 2 2010, 12:15
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(MALLOY2 @ Dec 2 2010, 13:57)  я не знаю какой он у вас, и какой проц И проц крутой - STM32F103, и компилятор крутой - Keil RealView MDK-ARM 4.12 Цитата Но то что вы хотите сделать это гомнокод еще тот, даже и не думайте о таких подходах. И делать так не хочу. А подумать не помешает...  Цитата В самом крайнем случае заменить функции дефайнами, и то правильней будет ... и никакого оверхеда только можно таких багов нахвататься Оверхед остается, если принять во внимание, что иногда мне нужно сразу Control-Indication(), а иногда только Indication(). Цитата(MrYuran @ Dec 2 2010, 13:47)  Можно, но не так. Сделать внутри switch(), а переключатель передавать снаружи. Если с переключателем, так это еще более избыточно. Лучше уж 2 независимые функции.
|
|
|
|
|
Dec 2 2010, 12:15
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(MALLOY2 @ Dec 2 2010, 14:57)  В самом крайнем случае заменить функции дефайнами, и то прравельней будет. Но только не так, как у вас! Что, по-вашему, скажет компилер на конструкцию {}; Обычно макросы объявляют в скобках do{}while(0) А лучше всё-таки макросами не злоупотреблять, во избежание.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Dec 2 2010, 12:38
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Но только не так, как у вас! Что, по-вашему, скажет компилер на конструкцию {}; Про все компиляторы не скажу, но те с которыми я работаю такую конструкцию хавают.
|
|
|
|
|
Dec 2 2010, 13:16
|

Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 1-10-07
Из: НЧ
Пользователь №: 30 966

|
Цитата(MrYuran @ Dec 2 2010, 15:55)  Есть нюансы. Например, в конструкциях с if() При do{}while(0) ньюансы с if пропадают?
|
|
|
|
|
Dec 2 2010, 13:31
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Так и есть это и есть всякие баги с макросами  , Лично я исторически так сложилось всегда записываю только так Код if(...) { //даже если только 1 оператор используется. } else {
}
|
|
|
|
|
Dec 2 2010, 14:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Ну можно еще более универсальную штуку сочинить, типа: Код typedef void (*pVoidFun)(void);
void Control_Indication(pVoidFun p) { if(p) p(); Indication(); } Тогда можно вызывать Control_Indication(NULL) - будет вызываться только Indication(), а при вызове типа Control_Indication(Control) сначала вызовется функция, адрес которой вы передали вызывающей функции, затем Indication().
|
|
|
|
|
Dec 2 2010, 16:59
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (kosyak© @ Dec 2 2010, 16:39)  Занятная статья. do{}while(0) я видел в чужих исходниках пару раз - и никак не мог понять зачем? Спасибо, разъяснили.. Трюк, конечно, хороший, только надо тоже с аккуратностью применять, ибо: 1) Хороший компилятор выдаст предупреждение о том, что условие никогда НЕ выполняется, хотя все сделает правильно, но лишние вопли придется давить локальными прагамами - некузяво  . 2) Поганый компилятор (например, вот прямо сейчас работаю с рекордно поганым ImageCraft для M8C ) - такое НЕ соптимизирует - вообще гнусно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 2 2010, 18:17
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(_Pasha @ Dec 2 2010, 17:46)  ТХЕ БЕСТ оно будет когда все указанные функции объявим static. Прокомментирую сам. Квалификатор static будет иметь смысл, если я эти функции заброшу в отдельный файл. Таких функций у меня несколько десятков, что ж, мне, столько файлов создавать? Не вижу смысла. P.S. Где-то здесь и зарыта собака "неполной структурированности" языка C. P.P.S. По поводу do {...} while (0) - а чем плохо показанное в той же статье строчкой выше {...} ? Разве кто-то заставляет писать I2C_CLOCK() ; с точкой с запятой в конце? Или в дефайне можно было задать #define I2C_CLOCK(); {NOP(); SCL = 1; NOP(); SCL = 0;} Да, это не работает (кажется, в Hi-Tech PICC у меня получалось такое, а в Keil - нет)
|
|
|
|
|
Dec 3 2010, 07:03
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(MALLOY2 @ Dec 2 2010, 14:43)  Код void Combo(void) { Control(); Indication(); } Без комментариев. The Best  Еще один коментарий - если компилятор достаточно умный, то он из функции Combo сделает именно то, что было нужно ТС. Ну, может быть, с оверхедом на один jmp (И даже для не статических функций Control и Indication) PS. Пишите на FORTRAN'е - там это можно средствами языка
|
|
|
|
|
Dec 3 2010, 08:29
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Dec 2 2010, 21:17)  Прокомментирую сам. Квалификатор static будет иметь смысл, если я эти функции заброшу в отдельный файл. Таких функций у меня несколько десятков, что ж, мне, столько файлов создавать? Не вижу смысла. Пардон, не было времени на развернутый ответ. Код void Combo(void); void Control(void); void Indication(void); //............................................... static void Control_prim(void); static void Indication_prim(void); Имеем заготовки для того чтобы контрол и индикация вызывались как извне так и максимально оптимизированно Код void Combo(void) { Control_prim(); Indication_prim(); }
void Control(void) { Control_prim(); }
void Indication(void); { Indication_prim(); } Теперь великий смысел оберток, надеюсь понятен.
|
|
|
|
|
Dec 3 2010, 09:32
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(_Pasha @ Dec 3 2010, 10:29)  Теперь великий смысел оберток, надеюсь понятен.  Увы...  Не могли бы вы словами описать, за счет чего будет оптимизация. Пока что вижу разрастание кода... Как будет у меня: Код int main(void) { ... Control(); Indication(); ... Indication(); } void Control(void) { ... } void Indication(void) { ... } Другой вариант: Код int main(void) {... Control(); ... Indication(); } void Control(void) { ... Indication(); } void Indication(void) { ... }
|
|
|
|
|
Dec 3 2010, 12:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (ViKo @ Dec 3 2010, 11:41)  Например, так, без точки с запятой после макрофункции, Потом почесали за ухом и решили, что в процессе кования программы макрос разросся и лучше сделать из него обычную функцию. И помчались вставлять точку с запятой везде, где было использование этого макроса. И все ради чего? Ради того, чтобы по религиозным соображениям не использовать конструкцию do {} while(0) ? Да пожалуйста.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 3 2010, 13:39
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Собсна делов-то: Код #define Begin___Macro do{ #define End___Macro }while(0); И даже самый страшный и больной компилер пойдет туда, куда нада. ЗЫ: если дописать break;}while(0); например По сабжу: вообще-то логика организации программ на сях отличается от асмового. Например, если завести нечто типа машины Даффа и расположить жизненно важные части по раз и навсегда определенному приоритету, типа Код void system(char prio) { switch(prio) { case 0: remote_command(); case 1: indication(); case 2: control(); case 3: critical(); } } можно вызывать такое отовсюду и отрубать не актуальные функции входным параметром - приоритетом. Хотя я приверженец protothreads...
|
|
|
|
|
Dec 3 2010, 14:58
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Сергей Борщ @ Dec 3 2010, 14:53)  Потом почесали за ухом и решили, что в процессе кования программы макрос разросся и лучше сделать из него обычную функцию. И помчались вставлять точку с запятой везде, где было использование этого макроса. Когда я захочу вместо макроса применить функцию, я даже имени такого не оставлю, а изменю, согласно своим "религиозным" убеждениям. Заменить не трудно, при желании, можно даже автоматом. Я стараюсь не плодить лишних сущностей. Цитата(_Pasha @ Dec 3 2010, 15:39)  можно вызывать такое отовсюду и отрубать не актуальные функции входным параметром - приоритетом. Об этом написал MrYuran в посте №3
|
|
|
|
|
Dec 3 2010, 23:11
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Если функции инлайновые, а параметр константный, константный, это const? У меня есть некоторые сомнения по поводу const. Тут наверно правильнее сказать как-то так: определен на этапе компиляции. Но смысл Вашего поста понятен...Это я так, придираюсь )) Хотя, действительно продвинутый компилятор наверное и с const сработается...но это только догадки..
--------------------
The truth is out there...
|
|
|
|
|
Dec 4 2010, 13:13
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(sergeeff @ Dec 4 2010, 15:32)  TO _Pasha :
Сдается мне, что вы формулируете свои советы, основываясь на работе какого-то конкретного компилятора. То, про что вы пишете может быть так, а может и нет.
Даже функции, явно объявленные как inline, могут и не подставляться, если компилятор сочтет это не оптимальным решением. Александреску в одной из последних книг подробно все это рассматривает. Совершенно верно. Сильное влияние гцц. Однако, там хоть все эти пляски дают детерминированный результат. Чего не скажешь про остальной зоопарк. Вообще-то, как только замечаю "скользкости" - стараюсь их обходить раз и навсегда. Построением программы. Чуть позже потестирую, чтоб не быть голословным, наверняка будет интересно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|