Указатель функции Typedef?
Я учусь, как динамически загружать DLL, но я не понимаю, что это за строка
typedef void (*FunctionFunc)();
У меня есть несколько вопросов. Если кто-то сможет ответить на них, я был бы благодарен.
- Почему используется
typedef
? - Синтаксис выглядит странно; после
void
должно быть имени функции или чего-то еще? Это похоже на анонимную функцию. - Создан ли указатель на функцию для хранения адреса памяти функции?
Так что я смущен в данный момент; Вы можете уточнить вещи для меня?
Ответы
Ответ 1
typedef
- это языковая конструкция, которая связывает имя с типом.
Вы используете его так же, как и исходный тип, например
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
используя их как
myinteger i; // is equivalent to int i;
mystring s; // is the same as char *s;
myfunc f; // compile equally as void (*f)();
Как вы можете видеть, вы можете просто заменить указанное имя с указанным выше определением.
Трудность заключается в указателе на синтаксис и читаемость функций в 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); // call product() to calculate 123*456
Ответ 2
-
typedef
используется для псевдонимов; в этом случае вы используете FunctionFunc
для void(*)()
.
-
Действительно, синтаксис выглядит странно, посмотрите на это:
typedef void (*FunctionFunc) ( );
// ^ ^ ^
// return type type name arguments
-
Нет, это просто говорит компилятору, что тип FunctionFunc
будет указателем функции, он не определяет один, например:
FunctionFunc x;
void doSomething() { printf("Hello there\n"); }
x = &doSomething;
x(); //prints "Hello there"
Ответ 3
Без слова typedef
в С++ объявление объявит переменную FunctionFunc
указателя типа для функции без аргументов, возвращая void
.
В typedef
вместо этого он определяет FunctionFunc
как имя для этого типа.
Ответ 4
Если вы можете использовать С++ 11, вы можете использовать ключевое слово std::function
и using
.
using FunctionFunc = std::function<void(int arg1, std::string arg2)>;
Ответ 5
#include <stdio.h>
#include <math.h>
/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/
// typedef a primitive data type
typedef double distance;
// typedef struct
typedef struct{
int x;
int y;
} point;
//typedef an array
typedef point points[100];
points ps = {0}; // ps is an array of 100 point
// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)
// prototype a function
distance findDistance(point, point);
int main(int argc, char const *argv[])
{
// delcare a function pointer
distanceFun_p func_p;
// initialize the function pointer with a function address
func_p = findDistance;
// initialize two point variables
point p1 = {0,0} , p2 = {1,1};
// call the function through the pointer
distance d = func_p(p1,p2);
printf("the distance is %f\n", d );
return 0;
}
distance findDistance(point p1, point p2)
{
distance xdiff = p1.x - p2.x;
distance ydiff = p1.y - p2.y;
return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
}
Ответ 6
Для общего случая синтаксиса вы можете посмотреть приложение A стандарта ANSI C.
Оттуда в форме Бэкуса-Наура вы можете видеть, что typedef
имеет storage-class-specifier
.
В declaration-specifiers
типов вы можете видеть, что вы можете смешивать множество типов спецификаторов, порядок которых не имеет значения.
Например, правильно сказать,
long typedef long a;
определить тип a
в качестве псевдонима на long long
. Итак, чтобы понять typedef для исчерпывающего использования, вам нужно обратиться к некоторой форме backus-naur, которая определяет синтаксис (есть много правильных грамматик для ANSI C, не только для ISO).
Когда вы используете typedef для определения псевдонима для типа функции, вам нужно поместить псевдоним в то же место, где вы поместили идентификатор функции. В вашем случае вы определяете тип FunctionFunc
как псевдоним для указателя на функцию, чья проверка типа отключена при вызове и ничего не возвращает.