Указатель на функцию с переменным числом параметров

Arduino.ru

Указатель на функцию с переменным числом аргументов

Ситуация такая, передаю в функцию указатель на функцию.

Так работает замечательно, но если я передаю напрямую EEPROM.put(0,var); валятся ошибки.

Пробовал через шаблон то же не получаеться.

Так же с ошибками. Помогите разобраться.

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

И как же Вы это делаете? Секрет?

Памойму, это не адрес функции, а её вызов в этом месте.

Ну, скетча мы не видели, а потому, хрен его знает что там.

Var любого типа в том числе и структура.

Про лямдафункцию вчера начал читать, но поздно уже было. Сегодня продолжу изучение.

Уже начинаю понимать природу ощибок.

Действително я вызываю функцию, а не передаю.

Нужно делать как то так:

А вот как обработать передаваемые параметры и вставить их в функцию для меня пока загадка.

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

А что в этом страшного если не секрет?

Нужно делать как то так:

Нет, так делать не нужно. С шаблонами так не работают.

Если бы мой кругозор был настолко велик не было бы данной темы. Поэтому и обратился за помошью.

Нужно делать как то так:

Нет, так делать не нужно. С шаблонами так не работают.

а как нужно делать?

Пришол вот к такому виду.

Но если пытаюсь передать параметры все равно ошибки.

И да же если не шаблонную функцию передовать все равно не получаеться.

Немного нашел информации:

Вот кусок кода как пример что я хочу получить.

Забудем навсегда про EEPROM.put

Цель стоит не переписывать каздый раз конструкцию с millis().

А вынести ее в отдельную функцию передать предыдущее значение millis(), интервал и функцию которая дожна выполниться.

Все хорошо работает с void или когда известно число и тип аргументов функции.

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

а как нужно делать?

Вы можете внятно и спокойно объяснить что нужно сделать. Не предлагать свои решения, а просто сказать «что»?

Пришол вот к такому виду.

Давайте, я не будe комментировать 🙂

Если бы мой кругозор был настолко велик не было бы данной темы. Поэтому и обратился за помошью.

Немного нашел информации:

Вот кусок кода как пример что я хочу получить.

Ну, и где в этом коде передача указателя на функцию? Ещё раз, к началу моего поста, объясните наконец внятно, что же Вам нужно-то? Только внятно, словами, а не примерами и, Боже упаси, без Ваших идей готовых решений на лямбдах, шаблонах, или ещё на чём.

Пост выше я написал, что хочу получить.

И если не затруднит коментируйте 😉

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

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

Вы пытаетесь использовать шаблоны как мартышка очки. Угадал? Не выйдет, читайте нормальную литературу про шаблоны. Без понимания там трудно.

Ладно, сейчас я убегаю, вернусь в сеть вечером, попрбуйте пока понять что такое Т в Вашей записи и внимательно читайте в моём предыдущем посте что именно Вы на самом деле сделали.

Ну а я, как неугадавшый, самоудалюся

ПС: Просто иногда контрабандой из под полы предлагаю.Последнюю отдал.

Сдается мне что это не совсем то, что хочет в #11.

Надо в таймере на миллисе вызывать ф-ции с произвольным кол-вом аргументов, а тут в стр.7 вобще без аргумента. Понятно что сунув туда обертку на функцию с аргументами можна выкрутится через глобальные, как в стр.17 var сделана. Но наверно это не очень. У лямд там в [] можна койчего писать еще 😉 может так пройдет.

Читайте также:  Volvo xc90 дизель или бензин что лучше

Я бы шото такое пробовал. Собирается но передачу данных в Fn сами проверяйте.

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

Источник

С++ для начинающих Функции с переменным числом параметров

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

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

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

=========
Что можно увидеть? Первым делом внутри функции происходят взятие адреса первого параметра, при этом тип указателя должен совпадать с типом этого параметра. Дальше идет простой перебор всех параметров с помощью цикла.

Таким же образом можно привести классический пример суммирования элементов

while (* P ) //Пока встречаются параметры
<
sum = sum +(* P ) ” “ ; //Прибавляем к сумме то что взяли по адресу P
P ++; //Адресная арифметика. Смена текущего адреса на следующий
>


cout sum endl ; //Вывод результата на экран
>

Вообще весь этот механизм удобно использовать тогда, когда требуется обработка однотипных элементов и чем-то всё напоминает обычный массив элементов. Учитывая, что указатель должен быть того же типа, что и элемент, расположенный по адресу на который он ссылается, можно сказать, что переменное число параметров может быть корректно использовано как раз тогда, когда все параметры передаваемые в такую функцию принадлежат одному и тому же типу (имеются ввиду те параметры, которые идут туда где расположено многоточие).

Но вообще в функцию можно передавать произвольное число параметров с переменным типом, я не говорил, что этого сделать нельзя, можете перечитать всё снова, чтобы в этом убедиться. При определении функций с переменным количеством параметров, рекомендуется использовать специальный набор макроопределений, которые становятся доступными при включении в программу заголовочного файла stdarg.h

Эти макроопределения обеспечивают простой и стандартный (независящий от реализации) способ доступа к спискам параметров переменной длины. Я не буду расписывать, так как сам плохо все это представляю, но приведу пример, содранный с учебника Марченко А.Л. Бархатный путь (2005). Там более менее расписано что к чему и нарушать его авторство я не хочу. Но кое что оттуда вынесу

Источник

Функции с переменным числом параметров

Функции с переменным числом параметров

К ак уже обсуждалось ранее, по умолчанию параметры передаются функции через стек. Поэтому, технически, нет ограничения на количество передаваемых параметров – “запихать” можно сколько угодно. Проблема в том, как потом функция будет разбирать переданные параметры. Функции с переменным числом параметров объявляются как обычные функции, но вместо недостающих аргументов ставится многоточие. Пусть мы хотим сделать функцию, которая складывает переданные ей числа, чисел может быть произвольное количество. Необходимо каким-то образом передать функции число параметров. Во-первых, можно явно передать число параметров обязательным аргументом. Во-вторых, последний аргумент может иметь некоторое «терминальное» значение, наткнувшись на которое функция закончит выполнение.
Общий принцип работы следующий: внутри функции берём указатель на аргумент, далее двигаемся к следующему аргументу, увеличивая значение указателя.

OLD SCHOOL

Д елаем всё вручную. Функция, которая складывает переданные ей аргументы

Первый параметр – число аргументов. Это обязательный параметр. Второй аргумент – это первое переданное число, это тоже обязательный параметр. Получаем указатель на первое число

Далее считываем все числа и складываем их. В этой функции мы также при сложении проверяем на переполнение типа unsigned.

Читайте также:  Что такое правило гостевых голов в футболе

Можно сделать первый аргумент необязательным и «перешагнуть» аргумент unsigned char num, но тогда возникнет большая проблема: аргументы располагаются друг за другом, но не факт, что непрерывно. Например, в нашем случае первый аргумент будет сдвинут не на один байт, а на 4 относительно num. Это сделано для повышения производительности. На другой платформе или с другим компилятором, или с другими настройками компилятора могут быть другие результаты.

Поэтому лучше число параметров, если это аргумент, сделать типом int или unsigned int.

Можно сделать по-другому: в качестве «терминального» элемента передавать ноль и считать, что если мы встретили ноль, то больше аргументов нет. Пример

Но теперь уже передавать нули в качестве аргументов нельзя. Здесь также есть один обязательный аргумент – первое переданное число. Если его не передавать, то мы не сможем найти адрес, по которому размещаются переменные в стеке. Некоторые компиляторы (Borland Turbo C) позволяют получить указатель на …, но такое поведение не является стандартным и его нужно избегать.

VA_ARG

М ожно воспользоваться макросом va_arg библиотеки stdarg.h. Он делает практически то же самое, что и мы: получает указатель на первый аргумент а затем двигается по стеку. Пример, та же функция, только с va_arg

Первый аргумент – число параметров – также лучше делать типа int, иначе получим проблему со сдвигом, кратным 4.

Макросы и типы для работы с переменным числом параметров

Название Описание
va_list Тип, который используется для извлечения дополнительных параметров функции с переменным числом параметров
void va_start(va_list ap, paramN) Макрос инициализирует ap для извлечения дополнительных аргументов, которые идут после переменной paramN. Параметр не должен быть объявлена как register, не может иметь типа массива или указателя на функцию.
void va_end(va_list ap) Макрос необходим для нормального завершения работы функции, работает в паре с макросом va_start.
void va_copy(va_list dest, va_list src) Макрос копирует src в dest. Поддерживается начиная со стандарта C++11

Неправильное использование

Если передано больше аргументов, то функция выведет только те, которые ожидала встретить

Так как очистку стека производит вызывающая функция, то стек не будет повреждён. Получается, что если изменить схему вызова и сделать так, чтобы вызываемый объект сам чистил стек после себя, то в случае неправильного количества аргументов стек будет повреждён. То есть, буде функция объявлена как __stdcall, в целях безопасности она не может иметь переменного числа аргументов.
Однако, если добавить спецификатор __stdcall к нашей функции summ она будет компилироваться. Это связано с тем, что компилятор автоматически заменит __stdcall на __cdecl.

Программа завершится с ошибкой вроде The value of ESP was not properly saved across a function call.

Источник

Макросы с переменным числом параметров

Недавно пришлось мне разбираться с одним Open Source проектом. Нужно было разобраться с одной ошибкой. Ошибка была плавающей и проявлялась исключительно на стенде, после получаса раб. Да и то не всегда. Поэтому было принято решение логировать определенные участки кода.

Поэтому была написана простая функция:
которая записывала строку в лог. Вскоре оказалось, что такой функции недостаточно и она была переписана в таком виде:
т.е. теперь она при помощи функции vfprintf() записывала в файл форматированную строку. По мере роста числа вызовов, захотелось писать в файл еще два параметра, а именно __LINE__ и __FILE__. Передавать эти два параметра при каждом вызове функции не хотелось, поэтому было принято решение написать макрос-обертку над функцией dbg(), который бы принимал переменное число параметров, вызывал исходную функцию и передавал бы ей двумя первыми параметрами имя файла и номер строки.

Погуглив, я нашел довольно красивое решение — описать класс и перегрузить в нем оператор (). Я набросал тестовый проект, протестировал новый макрос и измененную функцию и остался доволен результатом. После этого подключил файлы в исходный проект, h-файл заинклюдил в «StdAfx.h» и нажал Build. И тут меня настигло глубокое разочарование. Оказалась, что часть проекта написана на чистом Си, который имел в виду мои классы.

Погуглив еще, я нашел такое решение. Но увы, я использовал VC6…

И тогда меня посетила идея — а, что если макрос будет заменяться функцией, которая будет принимать параметры __FILE__ и __LINE__, сохранять их где нибудь и возвращать указатель на оригинальную функцию dbg(). А эта функция будет считывать сохраненные параметры и записывать их в файл. Параметры было решено сохранять в глобальные переменные. А сами переменные, дабы не нарваться на грабли при многопоточной работе, объявить как __declspec(thread). B вот, что получилось в итоге:

Вот и все. Единственное, на чем хотелось бы остановиться, это объявление функции DbgFuncRet()
Т.к. заголовок подключается и в c и в cpp файлы, то транслятор имен будет применять разные декорации для функции. А такое объявление говорит транслятору всегда использовать декорацию C.

Источник

Электроника для всех

Блог о электронике

1.5.2. Вызов функции с переменным числом параметров

При вызове функции с переменным числом параметров в вызове этой функции задается любое требуемое число аргументов.

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

Все аргументы, заданные в вызове функции, размещаются в стеке. Количество формальных параметров, объявленных для функции, определяется числом аргументов, которые берутся из стека и присваиваются формальным параметрам. Программист отвечает за правильность выбора дополнительных аргументов из стека и определение числа аргументов, находящихся в стеке.

Примерами функций с переменным числом параметров являются функции из библиотеки функций языка СИ, осуществляющие операции ввода-вывода информации (printf,scanf и т.п.). Подробно эти функции рассмотрены во третьей части книги.

Программист может разрабатывать свои функции с переменным числом параметров. Для обеспечения удобного способа доступа к аргументам функции с переменным числом параметров имеются три макроопределения (макросы) va_start, va_arg, va_end, находящиеся в заголовочном файле stdarg.h. Эти макросы указывают на то, что функция, разработанная пользователем, имеет некоторое число обязательных аргументов, закоторыми следует переменное число необязательных аргументов. Обязательные аргументы доступны через свои имена как при вызове обычной функции. Для извлечения необязательных аргументов используются макросы va_start, va_arg, va_end в следующем порядке.

Макрос va_start предназначен для установки аргумента arg_ptr на начало списка необязательных параметров и имеет вид функции с двумя параметрами:

Параметр prav_param должен быть последним обязательным параметром вызываемой функции, а указатель arg_prt должен быть объявлен с предопределением в списке переменных типа va_list в виде:

Макрос va_start должен быть использован до первого использования макроса va_arg.

Макрокоманда va_arg обеспечивает доступ к текущему параметру вызываемой функции и тоже имеет вид функции с двумя параметрами

Эта макрокоманда извлекает значение типа type по адресу, заданному указателем arg_ptr, увеличивает значение указателя arg_ptr на длину использованного параметра (длина type) и таким образом параметр arg_ptr будет указывать на следующий параметр вызываемой функции. Макрокоманда va_arg используется столько раз, сколько необходимо для извлечения всех параметров вызываемой функции.

Макрос va_end используется по окончании обработки всех параметров функции и устанавливает указатель списка необязательных параметров на ноль (NULL).

One thought on “1.5.2. Вызов функции с переменным числом параметров”

хотел сначала использовать printf. но почему-то никак не смог переопределить функции в файле write.c(как написано на разных сайтах). Потом решил написать свою упрощенную функцию для форматного вывода. Файл stdarg к проекту подключил, но ругается вот так :
Error[Pe007]: unrecognized token
на строку va_list ар;

Что я могу делать не так?

Добавить комментарий Отменить ответ

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

Источник

Читайте также:  К чему снится бывший ревнует во сне
Образовательный портал