Определение typedef для указателя на функцию?
Я изучаю, как динамически загружать DLL, но не могу понять следующую строку кода:
typedef void (*FunctionFunc)();
У меня есть несколько вопросов. Буду признателен, если кто-то сможет на них ответить.
- Зачем используется
typedef
? - Синтаксис выглядит странно; после
void
не должно быть имени функции или что-то подобное? Это выглядит как анонимная функция. - Создается ли указатель на функцию для хранения адреса памяти функции?
В данный момент я в замешательстве; не могли бы вы прояснить эти моменты для меня?
5 ответ(ов)
typedef
— это конструкция языка, которая связывает имя с типом.
Вы используете его так же, как и исходный тип, например:
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
И затем можно использовать эти типы следующим образом:
myinteger i; // эквивалентно int i;
mystring s; // то же самое как char *s;
myfunc f; // компилируется как void (*f)();
Как вы можете видеть, можно просто заменить имя, заданное с помощью typedef
, на его определение, приведенное выше.
Сложность заключается в синтаксисе указателей на функции и читаемости в C и C++, и typedef
может улучшить читаемость таких объявлений. Тем не менее, этот синтаксис оправдан, так как функции — в отличие от других более простых типов — могут иметь возвращаемое значение и параметры, что приводит к иногда длинным и сложным объявлениям указателей на функции.
Читаемость может стать действительно проблемной с указателями на массивы функций и другими еще более косвенными вариантами.
Теперь отвечая на ваши три вопроса:
Для чего используется
typedef
? Чтобы облегчить чтение кода — особенно для указателей на функции или имен структур.Синтаксис выглядит странно (в объявлении указателя на функцию)
Этот синтаксис не очевиден для восприятия, особенно для начинающих. Использование объявленияtypedef
облегчает понимание.Является ли указатель на функцию созданием для хранения адреса функции?
Да, указатель на функцию хранит адрес функции. Это не связано с конструкциейtypedef
, которая лишь упрощает запись/чтение программы; компилятор просто подставляет определениеtypedef
до компиляции реального кода.
Пример:
typedef int (*t_somefunc)(int,int);
int product(int u, int v) {
return u * v;
}
t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // вызов product() для вычисления 123*456
typedef
используется для создания псевдонимов типов; в этом случае вы создаете псевдонимFunctionFunc
для типаvoid(*)()
.Действительно, синтаксис может показаться странным, посмотрите на это:
typedef void (*FunctionFunc) ( ); // ^ ^ ^ // возвращаемый тип имя типа аргументы
Нет, это просто сообщает компилятору, что тип
FunctionFunc
будет указателем на функцию, это не определяет его, как в примере:FunctionFunc x; void doSomething() { printf("Hello there\n"); } x = &doSomething; x(); // выводит "Hello there"
Без слова typedef
в C++ объявление будет задавать переменную FunctionFunc
как указатель на функцию без аргументов, возвращающую void
.
С использованием typedef
вместо этого определяется FunctionFunc
как имя для этого типа.
Если вы можете использовать C++11, имеет смысл воспользоваться std::function
и ключевым словом using
. Это позволит вам создать алиас для функционального типа, что упростит чтение и использование кода. Например:
using FunctionFunc = std::function<void(int arg1, std::string arg2)>;
Таким образом, FunctionFunc
теперь является типом, представляющим функцию, которая принимает два аргумента: int
и std::string
, и не возвращает значения. Вы сможете удобно использовать этот алиас в дальнейшем в вашем коде для объявления переменных или параметров функций нужного типа.
Ваша задача заключается в том, чтобы понять, как использовать typedef
для определения новых типов в языке C. В приведенном вами коде используются различные примеры использования typedef
, включая примитивные типы, структуры, массивы и функции. Давайте рассмотрим их подробнее.
Определение примитивного типа:
Здесь мы создаем новый тип данных дляdouble
, который названdistance
:typedef double distance;
Определение структуры:
Мы определяем новую структуруpoint
, которая содержит две целочисленные координатыx
иy
:typedef struct { int x; int y; } point;
Определение массива структур:
Мы создаем типpoints
, который является массивом из 100 структурpoint
:typedef point points[100];
Определение указателя на функцию:
Здесь мы создаемtypedef
для указателя на функцию, которая принимает два параметра типаpoint
и возвращаетdistance
:typedef distance (*distanceFun_p)(point, point);
Прототип функции:
Мы объявляем функциюfindDistance
, которая будет находить расстояние между двумя точками:distance findDistance(point, point);
Главная функция:
Вmain
мы объявляем указатель на функциюfunc_p
, инициализируем его адресомfindDistance
, создаем две точкиp1
иp2
и вызываем функцию через указатель:distance d = func_p(p1, p2);
Определение функции:
В функцииfindDistance
мы вычисляем расстояние между двумя точками, используя теорему Пифагора:return sqrt((xdiff * xdiff) + (ydiff * ydiff));
Таким образом, используя typedef
, вы можете делать ваш код более читабельным и удобным для работы с новыми типами данных.
Разница между const int*, const int * const и int * const?
Как изменить цвет вывода echo в Linux
Почему переменные нельзя объявлять в операторе switch?
Как вывести список символов из .so файла?
`unsigned int` против `size_t`: когда и что использовать?