#c
Вопрос:
У меня есть ноющее подозрение, что об этом уже спрашивали раньше, но я его не нахожу…
Предположим, у меня есть typedef для функции A, которая принимает указатель на функцию с typedef B, которая, в свою очередь, принимает функцию typedef A. Если бы одна из них была структурой, я знаю, как бы я обрабатывал прямое объявление, но для функций я не знаю синтаксиса. Есть ли такой?
Я хочу быть в состоянии сделать:
typedef void (*function_A_t)(function_B_t f_B);
typedef void (*function_B_t)(function_A_t f_A);
Есть какие-нибудь намеки? Еще лучше, ссылка? Кстати, это на самом деле только что произошло со мной, но я смог исправить это по-другому, хотя на самом деле это было бы более плавным (лучше развязаться, меньше шансов, что следующий парень все испортит), если это возможно.
Ответ №1:
Вы можете сделать это, воспользовавшись тем фактом, что C указывает, что объявление функции без аргументов означает, что оно принимает неопределенное количество аргументов.
Таким образом, вы могли бы сделать это следующим образом:
typedef void (*function_A_t)(void (*)());
typedef void (*function_B_t)(function_A_t f_A);
Что позволяет скомпилировать следующее:
void A(function_B_t b)
{
b(A);
}
void B(function_A_t a)
{
a(B);
}
int main()
{
function_A_t a = A;
function_B_t b = B;
a(B);
b(A);
return 0;
}
В разделе 6.7.6.3p15 стандарта C говорится следующее относительно совместимости типов функций:
Для совместимости двух типов функций оба должны указывать совместимые типы возвращаемых данных. Кроме того, списки типов параметров, если присутствуют оба, должны совпадать по количеству параметров и использованию многоточия; соответствующие параметры должны иметь совместимые типы. Если у одного типа есть список типов параметров, а другой тип указан декларатором функций, который не является частью определения функции и содержит пустой список идентификаторов, список параметров не должен иметь многоточия, и тип каждого параметра должен быть совместим с типом, который является результатом применения повышений аргументов по умолчанию. Если у одного типа есть список типов параметров, а другой тип задан определением функции, содержащим (возможно, пустой) список идентификаторов, оба должны согласовываться по количеству параметров, и тип каждого параметра прототипа должен быть совместим с типом, который является результатом применения повышений аргумента по умолчанию к типу соответствующего идентификатора. (При определении совместимости типов и составного типа каждый параметр, объявленный с типом функции или массива, принимается как имеющий скорректированный тип, а каждый параметр, объявленный с определенным типом, принимается как имеющий неквалифицированную версию своего объявленного типа.)
Часть, выделенная жирным шрифтом выше, указывает, что void (*)()
совместима с void (*)(function_B_t)
Комментарии:
1. К каким версиям C это относится?
2. Кроме того, правильно ли я понимаю, что это будет работать, но уменьшит способность компилятора проверять списки параметров в момент вызова?
3. @Basya Приведенная выше стандартная цитата взята из C11, но она применима к C89 и более поздним версиям. И да, это позволит использовать любой указатель на функцию, который имеет
void
тип возвращаемого значения в качестве параметра. Это не идеально, но лучшее, что мы можем сделать.4. Спасибо! Я программирую на Си уже много лет, и это было для меня в новинку…
5. @dbush Это здорово! Отдельное спасибо за ссылку на стандарт.