|
|
  |
Функция, которая возвращает указатель на саму себя, как описАть? |
|
|
|
Apr 10 2007, 13:15
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
"То бензин, а то дети..." (это я про Дельфи и Си  ) Товарищу, вероятно, просто пример нужен. Вы, уважаемый zltigo, уже как-то постили простенькую расталдычку для начинающих про указатели и скобки - ссылку на нее прибить бы вверху всех форумов, где потенциально могут спрашивать про Си  . Функция, ничего не получающая и не возвращающая: void foo(void); Указатель на функцию, ничего не получающую и не возвращающую: void (void)* fptr; Функция, получающая указатель на функцию, ничего не получающую и ничего не возвращающую, и его же возвращающая: void (void)* foo(void (void)*); Соответственно, имплементация void (void)* foo(void (void)* fptr) { return fptr; } Как не сложно заметить, действо это совершенно бессмысленное (достаточно просто объявить переменную типа "указатель на функцию" и присвоить ей значение указателя на требуемую функцию без дополнительных телодвижений в виде функции, возвращающей указатель), что и вызвало недоумение уважаемого zltigo. UPD: т.е. достаточно: void foo(void); void (void)* fptr; fptr = &foo;
|
|
|
|
|
Apr 10 2007, 14:18
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Как возвращать указатель на функцию, которая ничего не возвращает, я знаю. Мне нужно немного другое. Возвращать нужно не ЛЮБОЙ указатель, а именно указатель на функцию, себе подобную. То есть получается как бы рекурсия в объявлении типа. Объясню на примере:
typedef ??????? // здесь обьявляется funcPtrType
extern char RxByte(void); // читает байт из UART
funcPtrType StartFunc(char Abyte) // фукнция обработки данных №1 funcPtrType Rx1Func(char Abyte); // фукнция обработки данных №2 funcPtrType Rx2Func(char Abyte); // фукнция обработки данных №3 funcPtrType EndFunc(char Abyte); // фукнция обработки данных №4
//************************************** // прерывание приема данных по UART //************************************** viod UART_RX(void){ char RxByte; static funcPtrType funcPtr; // хранит указатель на текущую фукнцию обработки принятого байта
RxByte = UDR; if (funcPtr == NULL) funcPtr = &StartFunc;
funcPtr = (*funcPtr)(RxByte); //обрабатываем принятий байт и возвращаем указатель // на функцию, которая будет вызвана в следующий раз
}
//************************************** funcPtrType Rx1Func(char Abyte) { .... // обрабатываем Abyte if (Abyte != 0x01) return &Rx1Func; // при следующеем приеме возвращаемся в эту же функцию else return &EndFunc; // }
//************************************** funcPtrType Rx2Func(char Abyte) { .... // обрабатываем Abyte if (Abyte != 0x01) return &Rx1Func; // при следующеем приеме возвращаемся в эту же функцию else return &EndFunc; // } //************************************** funcPtrType EndFunc(char Abyte) { if (Abyte =='A') return &Rx1Func; if (Abyte == 'B') return &Rx2Func; return NULL; } //************************************** funcPtrType StartFunc(char Abyte) { if (Abyte ==0x01) return &Rx1Func; if (Abyte ==0x02) return &Rx2Func; return NULL; }
Можно, конечно, объявить funcPtr как глобальную, и в фукнциях обработки данных (StartFunc, EndFunc, Rx1Func, Rx2Func) напрямую присваивать ей значения. Но такой подход меня пока не устраивает.
|
|
|
|
|
Apr 10 2007, 15:05
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Цитата(Александр Куличок @ Apr 10 2007, 19:18)  Как возвращать указатель на функцию, которая ничего не возвращает, я знаю. Мне нужно немного другое. Возвращать нужно не ЛЮБОЙ указатель, а именно указатель на функцию, себе подобную. То есть получается как бы рекурсия в объявлении типа. Объясню на примере:
typedef ??????? // здесь обьявляется funcPtrType
extern char RxByte(void); // читает байт из UART
funcPtrType StartFunc(char Abyte) // фукнция обработки данных №1 funcPtrType Rx1Func(char Abyte); // фукнция обработки данных №2 funcPtrType Rx2Func(char Abyte); // фукнция обработки данных №3 funcPtrType EndFunc(char Abyte); // фукнция обработки данных №4
... Я бы рекомендовал пересмотреть дизайн этой части программы. Слишком уж он хитромудрый. Но если не хочется, то может быть использовать массив указателей на функцию возвращающую, скажем uint8, который будет являтся индексом в массиве указателей. Приведенный код практически не изменится.
|
|
|
|
|
Apr 10 2007, 15:36
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата(shreck @ Apr 10 2007, 15:05)  Я бы рекомендовал пересмотреть дизайн этой части программы. Слишком уж он хитромудрый. Но если не хочется, то может быть использовать массив указателей на функцию возвращающую, скажем uint8, который будет являтся индексом в массиве указателей. Приведенный код практически не изменится. Это тоже оди из выходов, но не совсем то, чего хотелось бы. Очень не хочется привязывать имена функций к цифрам. А хитромудрость на самом деле кажущаяся. Дело в том, что подобных функций-обработчиков будет не одна даже не 10, а штук под 50. Они будут размещаться в разных модулях (своя цепочка обработчиков - в своем модуле) и обрабатывать каждая свою последовательность данных (которые поступают по УАРТ) - т.е реализовывать свой протокол. При этом должна быть возможность легко добавлять в программу дополнительные протоколы.
|
|
|
|
|
Apr 10 2007, 15:40
|

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

|
Цитата(Александр Куличок @ Apr 10 2007, 13:18)  Возвращать нужно не ЛЮБОЙ указатель, а именно указатель на функцию, Читать я все это не стал, извините, обсуждать архитктуру - тоже. Но "любой" преобразуется в нужный при использовании спокойно: Код void *dummy_func(void) { return( (void *)dummy_func ); }
void main(void) { ((void *(*)(void))dummy_func())();
}
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 10 2007, 15:57
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата(YemZ @ Apr 10 2007, 15:29)  typedef void* (*funcPtrType)(char);
т.е. funcPtrType – это указатель на функцию, принимающую байт и возвращающую бестиповый указатель
Возвраты из функций обработки должны выглядеть так return (funcPtrType)&Rx1Func;
Выделенная строка тоже обзаведется приведением типа funcPtr = (funcPtrType)((*funcPtr)(RxByte)); Кстати такие варианты тоже верны: return (funcPtrType)Rx1Func; funcPtr = (funcPtrType)(funcPtr(RxByte)); БОЛЬШОЕ СПАСИБО. Это то, что мне надо. Еще хотелось бы узнать - цепочки данных (деревья) в С реализуются точно так же? (Там аналогичная задача при описании структуры - она должна содержать ссылку на саму себя)
|
|
|
|
|
Apr 10 2007, 16:18
|

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

|
Цитата(Александр Куличок @ Apr 10 2007, 14:57)  Еще хотелось бы узнать - цепочки данных (деревья) в С реализуются точно так же? Кажется вопрос деревьев (связанных списков) рассматривается в любой книжке по C Код struct my_struct { my_struct *prev; my_struct *next; ........ }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|