5

Определение typedef для указателя на функцию?

17

Я изучаю, как динамически загружать DLL, но не могу понять следующую строку кода:

typedef void (*FunctionFunc)();

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

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

В данный момент я в замешательстве; не могли бы вы прояснить эти моменты для меня?

5 ответ(ов)

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
2
  1. typedef используется для создания псевдонимов типов; в этом случае вы создаете псевдоним FunctionFunc для типа void(*)().

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

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

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    
    x(); // выводит "Hello there"
    
0

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

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

0

Если вы можете использовать C++11, имеет смысл воспользоваться std::function и ключевым словом using. Это позволит вам создать алиас для функционального типа, что упростит чтение и использование кода. Например:

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;

Таким образом, FunctionFunc теперь является типом, представляющим функцию, которая принимает два аргумента: int и std::string, и не возвращает значения. Вы сможете удобно использовать этот алиас в дальнейшем в вашем коде для объявления переменных или параметров функций нужного типа.

0

Ваша задача заключается в том, чтобы понять, как использовать typedef для определения новых типов в языке C. В приведенном вами коде используются различные примеры использования typedef, включая примитивные типы, структуры, массивы и функции. Давайте рассмотрим их подробнее.

  1. Определение примитивного типа:
    Здесь мы создаем новый тип данных для double, который назван distance:

    typedef double distance;
    
  2. Определение структуры:
    Мы определяем новую структуру point, которая содержит две целочисленные координаты x и y:

    typedef struct {
        int x;
        int y;
    } point;
    
  3. Определение массива структур:
    Мы создаем тип points, который является массивом из 100 структур point:

    typedef point points[100];
    
  4. Определение указателя на функцию:
    Здесь мы создаем typedef для указателя на функцию, которая принимает два параметра типа point и возвращает distance:

    typedef distance (*distanceFun_p)(point, point);
    
  5. Прототип функции:
    Мы объявляем функцию findDistance, которая будет находить расстояние между двумя точками:

    distance findDistance(point, point);
    
  6. Главная функция:
    В main мы объявляем указатель на функцию func_p, инициализируем его адресом findDistance, создаем две точки p1 и p2 и вызываем функцию через указатель:

    distance d = func_p(p1, p2);
    
  7. Определение функции:
    В функции findDistance мы вычисляем расстояние между двумя точками, используя теорему Пифагора:

    return sqrt((xdiff * xdiff) + (ydiff * ydiff));
    

Таким образом, используя typedef, вы можете делать ваш код более читабельным и удобным для работы с новыми типами данных.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь