Указатель функции typedef?

376

Я изучаю динамическую загрузку DLL, но я не понимаю, что это строка

typedef void (*FunctionFunc)();

У меня есть несколько вопросов. Если кто-то сможет ответить на них, я буду благодарен.

  • Почему используется typedef?
  • Синтаксис выглядит нечетным; после void не должно быть имени функции или чего-то еще? Это похоже на анонимную функцию.
  • Является ли указатель функции создан для хранения адреса памяти функции?

Итак, я в замешательстве; можете ли вы прояснить мне все это?

  • 5
    Взгляните на ссылку (последний раздел) learncpp.com/cpp-tutorial/78-function-pointers
  • 6
    Следует отметить, что, поскольку c ++ 11 using FunctionFunc = void (*)(); может быть использован вместо Чуть более понятно, что вы просто объявляете имя для типа (указатель на функцию)
Показать ещё 2 комментария
Теги:
pointers
typedef

5 ответов

408
Лучший ответ

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
  • 5
    в последнем примере, просто «квадрат» не ссылается на то же самое, то есть указатель на функцию вместо использования & квадрат.
  • 2
    Вопрос: в вашем первом примере с typedef у вас есть typedef type alias но с указателями на функции, кажется, только 2 аргумента, typedef type . По умолчанию псевдоним - имя, указанное в аргументе типа?
Показать ещё 7 комментариев
172
  1. typedef используется для псевдонимов; в этом случае вы используете FunctionFunc для void(*)().

  2. Действительно, синтаксис выглядит странно, посмотрите на это:

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
    
  3. Нет, это просто говорит компилятору, что тип FunctionFunc будет указателем функции, он не определяет один, например:

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    
    x(); //prints "Hello there"
    
  • 23
    typedef не объявляет новый тип. у вас может быть много определяемых typedef имен одного и того же типа, и они не отличаются (например, от перегрузки функций). Существуют некоторые обстоятельства, при которых в отношении того, как вы можете использовать имя, определенное с помощью typedef имя не совсем эквивалентно тому, как оно определено, но множественные определяемые с помощью typedef имена для одного и того же, эквивалентны.
  • 0
    Ах, теперь я понял. Благодарю.
Показать ещё 2 комментария
26

Без слова typedef в С++ объявление объявит переменную FunctionFunc указателя типа для функции без аргументов, возвращая void.

В typedef вместо этого он определяет FunctionFunc как имя для этого типа.

  • 4
    Это действительно хороший способ думать об этом. Если вы внимательно прочитаете другие ответы, они на самом деле не решают путаницу ОП относительно запутывания псевдонима и имени. Я узнал что-то новое, прочитав этот пост.
8

Если вы можете использовать С++ 11, вы можете использовать ключевое слово std::function и using.

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;
  • 0
    без C ++ 11 using ключевого слова было бы похоже на typedef std::function<void(int, std::string)> FunctionFunc; На всякий случай, если кто-то хочет другую оболочку для функций без C ++ 11
1
#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) );
}
  • 1
    При каких обстоятельствах требуется '&'? Например, одинаково ли хорошо работают func_p = & findDistance и func_p = findDistance?
  • 1
    Имя функции является указателем, поэтому вам не нужно использовать «&» с ним. Другими словами, '&' является необязательным, когда рассматриваются указатели на функции. Однако для примитивного типа данных вам нужно использовать '&', чтобы получить его адрес.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню