Содержимое переменной как указатель на функцию.
- Войдите на сайт для отправки комментариев
Здравствуйте форумчане!
Искал искал, вроде бы нашел. На деле оказалось мало понятно как можно применить то что я задумал из того материала что я успел нагуглить. Вполне возможно что я вовсе не то ищу. Прошу вашей подсказки)
Есть мысль о неком устройстве, которое принимает разного рода команды. Мол, а сколько времени, а померяй-ка температуру, перезагрузись, расскажи о чем думаешь в данный момент и так далее.
Начал я писать такой код (опустим сбор данных из uart)
execBuffer = uartBuffer; if (execBuffer == "getTemerature") getTemperature(); if (execBuffer == "getVarMassives") getVarMassives(); if (execBuffer == "reboot") reboot(); void getTemperature(){ // measure } void getVarMassives(){ //get some vars and send } void reboot(){ //rebooting requence }
И тут меня начал душить перфекционист, мол какого "трехногого осьминога" я пишу
if (execBuffer == "getTemerature") getTemperature();
если в содержимом переменной уже содержится имя функции необходимой к выполнению.
По сути нужно сказать программе \ компилятору "дружок, вот в этой переменной есть имя функции которую нужно запустить"
Надеюсь что вас тоже смутило, это значит что вы меня понимаете.
Если количество функций выдет в 10 это будет как пом мне кака-код
Я пытался понять как именно можно вызвать функцию из переменной. Стало известно чть есть некие указатели * и ссылки $ но применить их примерно так
*execBuffer;
Это было бы идеально, но оно не работает.
Я бы использовал скажем switch()
Но мое жесткое делание использовать человекоимена там не свойственны. Там только цифры. Как быть, как жить товарщи? Есть варианты? Куда хоть копать?
ПС: а подумать?
Благодарю за очень объемный ответ который приблизил меня к решению задачи ровно на 0,00 %
И все же. Мои попытки я исчерпал. Сюда обращаюсь в том самом крайном случае и стараюсь не завешивать форум вопросами мол "я новичок, памагити". Знаете, подскажите, не знаете - мимо проходите.
#248
Я пытался понять как именно можно вызвать функцию из переменной. Стало известно чть есть некие указатели * и ссылки $ но применить их примерно так
Это было бы идеально, но оно не работает.
Я бы использовал скажем switch()
Но мое жесткое делание использовать человекоимена там не свойственны. Там только цифры. Как быть, как жить товарщи? Есть варианты? Куда хоть копать?
Как я понял Вам нужен массив указателей на функции
Пример скетча
Петр, сдается мне что своим примером Вы привели ТС-а в состояние "за" полной жопой из №1. :)
Функции в С по именам не вызываются, нигде не хранится информация об имени функции. У функции можно только взять адрес и вызвать ее по адресу. Решение напрашивается такое: для всех имен функций (в текстовом виде) заранее вычислить хэш или контрольную сумму по простейшему алгоритму, чтобы каждой строке соответствовал свой хэш, вариантов масса, надо пошерстить гуголь по ключевым словам "хэш строки". Потом создать 2 постоянных массива, один с хэшами всех названий функций, второй с соответствующими им адресами. При поступлении строки - вычислять её хэш, и искать в первом массиве. Если нашол такой хэш, брать адрес функции, который лежит по тому же индексу в другом массиве и вызывать её. Я счас не за компом, с планшета код писать неудобно. Если нада примерчег, то только пожже. Но я думаю, лагаритм понятен.
Я в сишном коде видел типа такого может оно имеет какой-то смысл (ссаными тряпками не кидать):
этта шо?
Это "метки" для goto, который хоть и запрещен, но все же существует. :)
синтакически верно только так
иначе не компилируеца. Вот только какова польза отэтова?
синтакически верно только так
иначе не компилируеца. Вот только какова польза отэтова?
откуда я знаю, в васике это указатель на адрес перехода, а вот зачем это в СИ сейчас и узнаем, я жеж говорю, увидел...и даже подивился )))
goto, который хоть и запрещен
Интересное кино. Можно поподробнее, когда, кем, номер и дата документа?
goto, который хоть и запрещен
Интересное кино. Можно поподробнее, когда, кем, номер и дата документа?
в 90ые у нас преподаватели любили это повторять, по мне так нормальная команда, вполне себе удобная.
в 90ые у нас преподаватели любили это повторять, по мне так нормальная команда, вполне себе удобная.
поскольку все мои знания о Си и о программировании вообще именно оттуда - из 80-90х, то я вырос с тем, что использования goto - признак программиста неудачника :) За все годы ни в одной моей программе ни одного goto не затесалось - даже в самых первых - и ни разу как-то и не было нужды.
как хорошо что я не программист :)
Вы напоминаете чукчу из анекдота:
UserDead,
информация об именах функция во время выполнения недоступна (если не пользоваться всякими чуждыми языку приблудами для загаживания памяти, типа отладочных баз или RTTI).
То, что Вы пытаетесь сделать, я бы делал более системно и об этом кстати, уже не раз вопрос поднимался, но более широко, чем у Вас.
Вопрос ставился так: хочется иметь возможность выполнить произвольную программу на удалённом контроллере так, чтобы не мешать его работе - не перепрошивать, не перезагружать и т.п.
Идея была использовать какой-нибудь простой, допускающий компактную реализацию интерпретатора язык (пока остановились на диалекте языка Форт). Интерпретатор должен сидеть в контроллере (вместе с его основной прошивкой) и по мере поступления команд, интерпретировать их.
При таком походе можно строить любые диагностические сценарии. Например, вывести HIGH на такой-то пин и посмотреть, что появилость на другом пине и т.п.
В этом языке должна быть возможность выполнять все штатные функции среды и заодно функции основной прошивки.
В принципе это делается не так уж сложно. Главное, чтобы хватало памяти "ещё и на интерпретатор", но до железа этот проект пока не доводился.
Допустим имеем функцию вида
Для того что бы красиво работать с указателем на нее опишем нужный нам тип
Теперь мы имеем нужный тип данных (указатель на требуемую нам функцию, и можем им оперировать)
Может что написал не по русски, ногами не пинать.
Вы напоминаете чукчу из анекдота:
хм...не понял.
Объсняю на пальцах:
1.Форум называется Ардуино. Здесь собираются те кому интересна Ардуино.
2 Раздел называется Программирование . Здесь собираются те кому интересен такой аспект, как программирование. И чем сложнее проект, тем глубже надо изучать программирование.
3.
Так что ответ выходит только такой https://www.youtube.com/watch?v=twbYHR7cB5g
Значит, Кнут, Брукс мл., а также разработчики ядра линукса - неудачники. А главные "удачники" - это Вирт с Дейстрой и Хоаром :)))
Потому что Ваши предподаватели (считающие goto разновидностью терроризма, педофилии, курения и потребления необезжиренного молока) вдолбили в Вас что а) это неприлично и б) научили Вас хитрым, черезжопным приёмам разруливания простейших ситуаций, лишь бы обойтись без треклятого goto, и эти черезжопные приёмы стали для Вас естсвенными - Вы их используете даже не задумываясь, что порой один goto сократил бы Вам пяток флагов и десяток дополнительных проверок.
Собственно "вред goto" - религиозная догма, умело вбитая в головы поколениям.
Тем более, что в машинных кодах AVR только хардкор, только GOTO в виде jmp и branch.
Может быть не будем отвлекаться от темы топика :)
умеет qwone программировать без goto через ж.... - да ради бога.
Шибко плюсую!!!
А всё таки вопрос повис в воздухе, умеет компилятор по именам на метку передавать управление?
По идее не должен, одно как-бы данные, второе адреса, и процессор с архитектурой РИСК, так не далеко и до вирусов на микроконтроллерах...
позвольте с вами не согласится :) видимо я так называемый "структураст" и этого уже не изменить :)
а насчет того, что через goto все быстрее и проще -
"Для любой задачи существует простой и очевидный путь к решению. Но чаще всего этот путь неверный"
но это и правда оффтопик.
Шибко плюсую!!!
А всё таки вопрос повис в воздухе, умеет компилятор по именам на метку передавать управление?
по именам нет, по ссылка - запросто. Так что можно написать процедурку. которая по имени будет находить в массиве адрес... - получится почти то, что хочет ТС.
Правда это, имхо, совершенно избыточный изврат.
Значит, Кнут, Брукс мл., а также разработчики ядра линукса - неудачники. А главные "удачники" - это Вирт с Дейстрой и Хоаром :)))
Потому что Ваши предподаватели (считающие goto разновидностью терроризма, педофилии, курения и потребления необезжиренного молока) вдолбили в Вас что а) это неприлично и б) научили Вас хитрым, черезжопным приёмам разруливания простейших ситуаций, лишь бы обойтись без треклятого goto, и эти черезжопные приёмы стали для Вас естсвенными - Вы их используете даже не задумываясь, что порой один goto сократил бы Вам пяток флагов и десяток дополнительных проверок.
Собственно "вред goto" - религиозная догма, умело вбитая в головы поколениям.
Ха! Порадовали. С каких это пор Вы поете дифирамбы так любимому мною "пшел на"? Не ожидал-с, спасибо. :)
Всегда писал на этом форуме, что "всякий инструмент хорош, когда используется умело и по назначению", а также, "если из чемоданчика мастера выложить часть инструментов, его работа лучше не станет".
Я реально это здесь писал много раз. Помните, или ссылки нужны?
Не, не помню и ссылки не требуются ибо не интересно ни разу.
Немнонго по теме, немного не потеме. Но уже немного яснее.
Выражаю благодарность тем кто отписался и разъяснил про адреса / метки
То что написал brokly не понял. Ну как не понял. Я увидел функцию вложенную в функцию с передачей параметров - не то.
По примеру сказанному DetSimen была мысль такая: Каждая буква - это цифры в ASCII. Каким-то образом сконвертировать представиление из текста в набор цифр и использовать для каждой команды набор цифр в switch(ASCII) но есть то символы двух и трех значные даже если первые незаглавные символы от начала алфавита из двух цифр делать костыль на 3 буквы 97 98 99 a, b и c соответственно - найдичайший костыль. А остальное делить по три цифры чтобы разбить и сконвертировать строку... Уж не знаю какой нужно болеть болезнью чтобы реализовать такое. Но мозг ищет варианты...
То что написано вами ЕвгенийП, выглядит довольно объемно. Это прям станция с возможностью отладки на ходу. Чуть ли не движок. ( Осталось нейросеть для самокоррекции написать :D ) Мне бы давно следовало сказать что нужно экномить память и не засорять String-ами char-ами память, а использовать кодовые команды. С другой стороны я за понятность команд как со строны общения на уровне клиент-сервер-приложение, так и со стороны коммандования. Вот прям заводит мысль о том что в любой момент можно подкинуться шнурком к контроллеру и поспрашивать его понятными мне командами. Именно теми которыми я в него зашил. К примеру как на маршрутизаторах консольки (show running-config, config > interface ethernet 2 > enable, show version и так далее)
Может не парится и просто тупо выписать как я описал?
Правда тогда запиханная, простите "в задницу" функция №20, будет дольше всех вызываться пока контроллер по всем if-ам не побегает. Кака-кодинг?!
Получается чтобы реализовать задуманное. Нужно вычислить адрес каждой функции и создать таблицу связи (уже вижу двумерный массив) где адрес сопоставляется с именем функции. Мне достаточно будет просто обратиться к нужной ячейке и дать команду перейти на такой-то адрес хранящийся в двумерном массиве. А правда что при каждой перекомпиляции (или при перезагрузке) адреса меняются. Тогда получается понадобится инициализация в виде вычисления адресов функций каждый раз. Уже похоже на что-то серьезное.
UserDead, вот я и говорю,то что написал первым. Для вас это полная жопа=комплекс мероприятий. Но если бы нормально знали язык и трюки в нем, то все это счастье можно отправить компилятору, который со всем этим справляется.
Не благодари. Прогони все свои строки с именами функций через хэширование, и создай таблицу, как советовали выше. Входящее значение прогоняешь через хэш, и смотришь в таблице.
Теперь мне более понятно.
Не гуру в программировании, учусь пока не на книжках, а на опыте. Нахожу себе задачу, и думаю как решить избивая пальцы на клавиатуре в гугле, просматривая форумы и примеры.
Если найду, радуюсь и потом копипастом время от времени использую в других работах пока не выучу способ. А уж потом оптимизация, доработки.
Думаю настанет момент, когда хотелки станут не простыми, и на форуме в меня будут бросаться книжками))
Теперь посидите и подумайте: как поступите, если в функции нужно будет параметры передавать. Да и как свой код через полгода читать станете со всеми этими хэшами, няш-мяшами и прочей курагой.
Теперь посидите и подумайте: как поступите, если в функции нужно будет параметры передавать.
Лехко: общий стек, функция сама выгребает параметры извне. Как пример: есть парсер входящих команд, помимо имени функции - выгребает все параметры, хранит их в списке внутри себя. Тогда внутри функции мона делать что-то типа:
Так, сходу решение, что называется.
Я предложил подумать человеку, который только вчера про указатели узнал.
Да и есть у меня сомнения, что в данном случае наворачивание парсеров перевесит по удобству-экономии десяток-другой ифов.
Все просто. Если функция внутренняя то она принимает параметры. Если внешняя обычно она является коммандой а присущий параметр будет сидеть в глобальной переменной.
А вот читать для меня не проблема. Я обожаю комментировать код косле того как пришлось "набыдлокодить" в своем первом масштабном проекте. Это три модуля для одной цели в одном устройстве где не менее 600 строк в каждом.
Как-то раз девайс сломался через пол года, и если бы не комментарии я бы рвал волосы сами знаете где в попытках вспомнить как это работает.
главное детям мороженое, а бабе цветы . И не перепутай кутузов.
Да и есть у меня сомнения, что в данном случае наворачивание парсеров перевесит по удобству-экономии десяток-другой ифов.
Ну это смотря какой проект ;) Скажем, когда несколько сотен команд - имхо лучше парсер, чем несколько сотен ифов.
Это три модуля для одной цели в одном устройстве где не менее 600 строк в каждом.
Три модуля всего лишь по 600 строк? Это зародыш проекта :), у вас всё ещё впереди. У меня в проектах частенько по несколько десятков тысяч строк кода - ничего, живём.
В том-то и дело, что сейчас у нас тут посреди вакуума стоит сферический конь. Думаю, что к тому времени, когда дело дойдет до сотни команд - подход неоднократно поменяется. Поэтому заранее предлагаю ТС оценить масштабируемость и контролируемость его идеи.
В том-то и дело, что сейчас у нас тут посреди вакуума стоит сферический конь.
Не, ну куда без этого то? Обижаете, рожать коней посреди ледянящих межзвёздных просторов - это местный старинный обычай, не будем его нарушать :)
Ну да . Сначала пишется некий "движок", некий "процессор" в котором указатели на функции есть его данные , или даже сказать управляемые "ноги", для вызова различных действий. Да что далеко ходить .Ядро выполнения всех даже не Си-шных языков реализовано на языке ... Си.
Тема - пример того как небольшая ошибка в начале проекта заводит в дебри а затем и тупик. Вот расскажите, UserDead, с чего Вы решили передавать команды строковыми переменными? Вам так удобней? Очень сомниваюсь. Разве что Вы их с клавиатуры вводите. Да и то проще можна.
Делайте так. Заводим h - файлик, имя protocol.h выглядит для него весьма уместным, в него пишем чтото типа
#include CMD_getTemerature 0
#include CMD_getVarMassives 1
и т.д Можете для продвинутости enum использовать.
Этот файл присутствует во всех проектах которые передают и принимают команды. Надо передать - ну пишите Send(CMD_getTemerature). По наглядности это ничем не хуже Send("getTemerature"). Даже лучше, притом компактей компилируется и быстрей работает. А функции при этом реализуются вобще легко и естественно. Пример массива указателей на функции с инициализацией есть в #4. Берете его, а индекс массива уже есть, это те самые CMD_ххххх. Получается принимаем команду cmd=Rcv(); и вызываем соответствующую функцию printSerial[cmd]();. Все просто и мульен раз пройдено, не страдайте фигней.
Иногда бывают ситуации когда действительно надо именно по строковым командам вызывать действия. Например при работе с модемом. Тогда это разумно описывать дето так.
Подробней тут http://arduino.ru/forum/apparatnye-voprosy/gsm-modem-a6-v-rezhime-tcp Но это если нет выхода, команды строковые.
Но это уже заводит нас в концептуальное программирование. Программирование через создание концепций.
Это заводит нас в пи... Потому как к макросам потребуеися дофига всего лишнего.
Я не понял: квон предлагает концептуальный проходной двор устроить из устройства что ли... Всю жись от инъекций защищались и на тебе, оказывается это модная вещь из коллекции "Весна-2018".
Нормально все . пишется некое ядро. А потом уже на месте с помощью макросов дотачивается до реальной конструкции. Правда тогда надо свой собственный язык для макросов разрабатывать. Но зато новый полет мысли в ардуиностроении.
Предлагаю на вход ардуине передавать инструкции честного Си. Это достаточно концептуально?