Как напечатать в Serial адрес указателя на функцию?
- Войдите на сайт для отправки комментариев
В попытках разобраться в своей проблеме, пришел к такому вопросу, но это уже другая тема.
Как получить конкретный адрес указателя на функцию?
Суть:
есть указатель на функцию, например такой
typedef void (*CONTROL) (void);
CONTROL control;
Ему присваивается значение (имя функции) например так:
control=func1;
НО, ведь реально ему присваивается не имя функции а её адрес в памяти. насколько я знаю адрес выражается в шестнадцатеричном формате.
Вот этот вот самый адрес и нужно как-то извлечь и напечатать в Serial, и соответственно затем выполнить обратную операцию:
получить в Serial некое значение (адрес) и присвоить его указателю.
попытка напечатать так Serial.println(control);
дает ошибку, что несовместимый тип (void) с функцией Serial.
Да и присваивание числа отличного от нуля, например так:
control=0x3B5F;
дает ошибку что пытаемся что-то присвоить void.
Вопрос - как быть?
можно нескромный вопрос - а зачем это?
для введения и сохранения настроек.
например нам нужно назначить новую функцию обработчик на какое-то событие, это событие вызывает обработчик по указателю, значит мы можем передать по Serial с компьютера адрес новой функции и теперь будет выполняться она.
Ну и что более важно - для сохранения текущего значения указателя в EEPROM. дело в том, что почему-то указатели сохраненные и вызванные затем из EEPROM как-то криво обрабатываются, приводя в непредсказуемым ошибкам, поэтому хотелось бы сохранять конкретный адрес указателя, как число, и затем задавать его обратно.
Предвижу предложение костыля: передавать некий идентификатор (1,2,3,4) и по нему уже в программе определять какое имя функции присвоить указателю.
Но я для того и затеял это, чтобы не расписывать полотна Switch case.. помоему это плохой стиль, да и влом.
Хотя стиль это вещь субъективна.
Тем не менее есть калссики Кернига Ритчи, Страуструп. Посмотрите их примеры. Switch case - не признак плохого стиля.
А вот задавать адрес чего то нибыло в ручную - это точно не в правилах хорошего тона...
Думаю если Вы вниматеотно поработаете с кодом то большинство проблемм рассосется.
Ато что Вы просите, сделать можно, такой пример думаю Вам поможет
Ну и что более важно - для сохранения текущего значения указателя в EEPROM. дело в том, что почему-то указатели сохраненные и вызванные затем из EEPROM как-то криво обрабатываются, приводя в непредсказуемым ошибкам, поэтому хотелось бы сохранять конкретный адрес указателя, как число, и затем задавать его обратно.
Уверяю Вас, транслятор обрабатывает ровно то что Вы ему прописали.
Ищите ошибки в коде, в первую очередь память, границы массивов и тд....
СПАСИБО Огромное!
Поковырял ваш пример, и вышло то что нужно!
Естетственно я не собирался задавать адреса в ручную, они ведь меняются все время (при перекомпиляции), суть была сделать примерно так:
Все работает, т.е. мы узнаем адрес указателя, присваиваем его переменной а из переменной обратно указателю, и все работает, печатается QWERTY, осталось проверить это с EEPROM!!
Только не совсем понял, зачем выводить af и &af - выводится одно и тоже значение, в чем разница, и что правильнее использовать для присвоения адреса переменной в строке 23?
Только не совсем понял, зачем выводить af и &af - выводится одно и тоже значение, в чем разница, и что правильнее использовать для присвоения адреса переменной в строке 23?
Это пример, показть как с указателями функции работать.
Блин... понял в чем косяк теперь... все дело в том что адреса меняются всякий раз.. т.е. если через однин скетч записывать, а потом просто закоментить строку записи, то адреса всех функций изменятся, и соотв. записанные в EEPROM указатели будут не туда указывать.. А я столько парился.. и мне говорили что RAM не хватает или еще что.. а выходит что сохранить в EEPROM актульные указатели вообще нельзя!
Тогда остается только такой вариант: передавать актуальные адреса функций на компьютер, и затем уже передавать их обратно ввиде параметров настроек, и сохранять в EEPROM. Тогда адреса останутся актуальными по идее, но уже получается не торт.. Хотя если есть способ сделать автоматический листинг всех функций в скетче, то еще можно поразмыслить.
Не стоит использовать указатели так как вы хотите их использовать. Нарушается целостность вашей программы. Сколько у вас функций? Обьявите enum и с его помощью пронумеруйте все функции, адреса функций поместите в массив. Общение с компом не по адресу как вы задумали, а просто по номеру функции. Получив номер функции ардуино сначала проверяет что номер не выходит за допустимые пределы, а потом достав по номеру адрес функции из массива передает управление нужной функции. Этот вариант сохранит целостность - что бы не передал на входе комп, управление будет гарантировано передано по правильному адресу
да, кстати массив пдресов лучше поместить в програмную память используя PROGMEM (изучите как эти пользоваться). Это еще улучшит стмбильность и избежите лишнего расхода RAM
Предложенный мной метод по сути тот же Switch, но при большом числе функций он удобнее
Спасибо, так и сделал, уместилось буквально в 3 строки. Насчет Progmem почитаю.
да, кстати массив адресов лучше поместить в програмную память используя PROGMEM (изучите как эти пользоваться). Это еще улучшит стмбильность и избежите лишнего расхода RAM
насчет экономии памяти верно, а какая стабильность и при чем она здесь ?