Автор Тема: Си, вопрос про функции и указатели  (Прочитано 5452 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Есть функция, например печатающая время, в которую передаются минуты через указатель:

Цитировать
void print_time (uint16_t *minutes);


Есть, например, диспетчер задач, запускающий функцию на через какое-то время через указатель:

Цитировать
extern unsigned int QueueDelay(void (*TaskPtr)(), unsigned int Ticks);


Запуск функций без параметров происходит отлично:

Цитировать
QueueDelay(Set_hour_min,500);


Но как передать туда функцию с параметрами? Так не работает, выдает ошибку:

Цитировать
QueueDelay(print_time (&min_alarm),500);
« Последнее редактирование: 24 Апреля 2014, 03:07:18 от admin »
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
@ Andy
В QueueDelay передается указатель на функцию, а не сама функция. Аргументы этой функции надо передать отдельно. То есть QueueDelay должна иметь вид:
Цитировать
extern unsigned int QueueDelay(void (*TaskPtr)(uint16_t *minutes), unsigned int Ticks, uint16_t *minutes)
{
    // blah-blah
    TaskPtr(minutes);
    // blah-blah
}

А когда ты пишешь QueueDelay(print_time (&min_alarm),500);
сначала выполняется print_time (&min_alarm), и возвращенное им значение подставляется в первый аргумент. То есть что-то вроде этого (на минутку забудем, что там void):
Цитировать
someresult = print_time (&min_alarm);
QueueDelay(someresult,500);
« Последнее редактирование: 24 Апреля 2014, 07:35:08 от pumpkin »

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Опять же можно ли в такую функцию
extern unsigned int QueueDelay(void (*TaskPtr)(uint16_t *minutes), unsigned int Ticks, uint16_t *minutes)

НЕ передавать параметр *minutes? В диспетчер надо будет передавать разные функции....

Или не парится и оборачивать функции с параментрами в функции без параметров - типа:

Цитировать
void print_time (uint16_t *minutes);
void alarm_print_time (void);

void alarm_print_time (void){
    print_time(&min_alarm);
}

QueueDelay(alarm_print_time, 500);


?
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
@ Andy

Приведи все Callback-функции к единому виду по аргументам и возвращаемым значениям, даже если не будешь использовать.  Обертки - это по сути то же самое.
Цитировать
void print_time (uint16_t* pminutes)
{
     printf("Minutes are: %d\\n", *pminutes);
}

void print_none(uint16_t* zzz)
{
     printf("Minutes are: None\\n");
}

unsigned int QueueDelay2(void (*TaskPtr)(uint16_t*), unsigned int Ticks, uint16_t* pminutes)
{
    TaskPtr(pminutes);
    return 0;   
}

int main(int argc, char *argv[])
{
    uint16_t min = 123;
    QueueDelay2(print_time, 500, &min);
    QueueDelay2(print_none, 500, NULL);
    return 0;
}

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
А не улетит ли функция по нулевому указателю на ресет? NULL - это ноль, не?

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

Спасибо!
« Последнее редактирование: 24 Апреля 2014, 10:16:02 от admin »
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Форум проекта "Минилаб-Мастер"


pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
Цитировать
А не улетит ли функция по нулевому указателю на ресет? NULL - это ноль, не?

Не улетит. print_time вызывается с ормальным значением, а print_none с NULL (можно что угодно сюда воткнуть), так как всё равно не использует его внутри себя.

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

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Ок, спасибо!
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Форум проекта "Минилаб-Мастер"