Я учусь динамически загружать DLL, но я не понимаю, что это за строка
typedef void (*FunctionFunc)();
У меня есть несколько вопросов. Если кто-то сможет ответить на них, я был бы благодарен.
- Почему
typedef
используется? - Синтаксис выглядит странно; после не
void
должно быть имени функции или чего-то еще? Это похоже на анонимную функцию. - Создан ли указатель на функцию для хранения адреса памяти функции?
Так что я в замешательстве в данный момент; Вы можете уточнить вещи для меня?
using FunctionFunc = void (*)();
можно использовать вместо. Чуть более понятно, что вы просто объявляете имя для типа (указатель на функцию)using FunctionFunc = void(void);
*
немного более явным.Ответы:
typedef
это языковая конструкция, которая связывает имя с типом.Вы используете его так же, как вы использовали бы, например, оригинальный тип
используя их как
Как видите, вы можете просто заменить имя typedefed определением, приведенным выше.
Сложность заключается в указателе на синтаксис функций и читаемость в C и C ++, и они
typedef
могут улучшить читаемость таких объявлений. Однако синтаксис является подходящим, поскольку функции - в отличие от других более простых типов - могут иметь возвращаемое значение и параметры, таким образом, иногда длинное и сложное объявление указателя на функцию.Читаемость может стать очень сложной с указателями на массивы функций и некоторые другие, даже более косвенные варианты.
Чтобы ответить на ваши три вопроса
Почему используется typedef? Для облегчения чтения кода - особенно для указателей на функции или структурные имена.
Синтаксис выглядит странно (в указателе на объявление функции) Этот синтаксис не очевиден для чтения, по крайней мере, в начале. Использование
typedef
декларации вместо этого облегчает чтениеСоздан ли указатель на функцию для хранения адреса памяти функции? Да, указатель функции хранит адрес функции. Это не имеет ничего общего с
typedef
конструкцией, которая только облегчает написание / чтение программы; компилятор просто расширяет определение typedef перед компиляцией фактического кода.Пример:
источник
typedef type alias
но с указателями на функции там только кажется , 2 аргумента,typedef type
. По умолчанию псевдоним - имя, указанное в аргументе типа?square
и&square
(и, действительно,*square
и**square
) все ссылаются на один и тот же указатель на функцию.typedef int newname
, вы делаетеnewname
псевдоним дляint
. С помощьюtypedef int (*func)(int)
вы создаетеfunc
псевдоним дляint (*)(int)
- указатель на функцию, принимающуюint
аргумент и возвращающуюint
значение.int (*func)(int)
я понимаю, что func - это псевдоним, немного запутанный, потому что псевдоним запутан с типом. Вtypedef int INT
качестве примера мне было бы легче, если бы указатель на функцию typedef имел формуtypedef int(*function)(int) FUNC_1
. Таким образом, я могу видеть тип и псевдоним в двух отдельных токенах, а не объединяться в один.typedef
используется для псевдонимов типов; в этом случае вы альясингFunctionFunc
кvoid(*)()
.Действительно, синтаксис выглядит странно, посмотрите на это:
Нет, это просто говорит компилятору, что
FunctionFunc
тип будет указателем на функцию, он не определяет его, например:источник
typedef
вовсе не объявить новый тип. у вас может быть многоtypedef
определенных имен одного и того же типа, и они не различаются (например, в случае перегрузки функций). Существуют некоторые обстоятельства, при которых в отношении того, как вы можете использовать имя,typedef
определенное имя не совсем эквивалентно тому, как оно определено, но несколькоtypedef
определенных имен для одного и того же эквивалентны.Без
typedef
слова, в C ++ объявление объявило бы переменнуюFunctionFunc
типа указатель на функцию без аргументов, возвращаяvoid
.С
typedef
вместо этого он определяетFunctionFunc
как имя для этого типа.источник
Если вы можете использовать C ++ 11, вы можете использовать
std::function
иusing
ключевое слово.источник
using
ключевого слова C ++ 11 будет похожеtypedef std::function<void(int, std::string)> FunctionFunc;
на случай, если кто-то захочет использовать другую оболочку для функций без C ++ 11источник
typedef (*double) p
typedef double* p
чтобы определить указатель на двойной. Если вы хотите заполнитьp
указатель из простой переменной, вам нужно использовать '&'. Примечание: мы * <имя указателя> разыменуем указатель.*
Используются в указателе функции разыменования указателя (имя функции) и перейти к блоку памяти , где находится инструкция функции.Для общего случая синтаксиса вы можете посмотреть в приложении A стандарта ANSI C .
В форме Бэкуса-Наура оттуда вы можете видеть, что
typedef
имеет типstorage-class-specifier
.В типе
declaration-specifiers
вы можете видеть, что вы можете смешивать множество типов спецификаторов, порядок которых не имеет значения.Например, правильно сказать,
определить тип
a
как псевдоним дляlong long
. Итак, чтобы понять typedef для исчерпывающего использования, вам нужно обратиться к некоторой форме backus-naur, которая определяет синтаксис (есть много правильных грамматик для ANSI C, не только для ISO).Когда вы используете typedef для определения псевдонима для типа функции, вам нужно поместить псевдоним в то же место, где вы поместили идентификатор функции. В вашем случае вы определяете тип
FunctionFunc
как псевдоним для указателя на функцию, чья проверка типа отключена при вызове и ничего не возвращает.источник