Синтаксис указателя функции C
У меня очень простой вопрос.
Обычно при объявлении некоторой переменной перед ней ставится ее тип, например:
int a;
указатель на функцию может иметь тип, подобный следующему: int(*)(int,int)
, если мы указываем на функцию, которая принимает два целых числа и возвращает целое число. Но при объявлении такого указателя его идентификатор не соответствует типу, например:
int(*)(int,int) mypointer;
вместо этого вы должны написать идентификатор в середине:
int(*mypointer)(int,int);
почему это так?
Извините, я знаю, это неловко простой вопрос...
Спасибо всем за ответ.
КАК.
Ответы
Ответ 1
Я объясняю это в своем ответе на вопрос: почему синтаксис C для массивов, указателей и функций был разработан таким образом? , и это в основном сводится к:
авторы языка предпочли сделать синтаксис переменной-ориентированной, а не ориентированной по типу. То есть, они хотели, чтобы программист просмотрел декларацию и подумал: "Если я напишу выражение *func(arg)
, это приведет к int
; если я напишу *arg[N]
меня будет float чем " func
должен быть указателем на функцию, которая принимает это и возвращает это".
Запись C в Википедии утверждает, что:
Идея Ричи заключалась в том, чтобы объявлять идентификаторы в контекстах, похожих на их использование: "декларация отражает использование".
... цитируя p122 группы K & R2.
Ответ 2
Эта структура отражает, как объявляется (и используется) нормальная функция.
Рассмотрим определение нормальной функции:
int foo (int bar, int baz, int quux);
Теперь рассмотрим определение указателя функции на функцию той же сигнатуры:
int (*foo) (int, int, int);
Обратите внимание, как две структуры отражают друг друга? Это делает *foo
гораздо легче идентифицировать как указатель на функцию, а не как нечто другое.
Ответ 3
Если вы имеете дело с функцией (не указателем на один), это имя также находится в середине. Он выглядит следующим образом: return-type function-name "(" argument-list ")" ...
. Например, в int foo(int)
, int
- это тип возвращаемого значения, foo
имя и int
список аргументов.
Указатель на функцию работает примерно так же - возвращаемый тип, затем имя, а затем список аргументов. В этом случае мы должны добавить *
, чтобы сделать его указателем, и (так как *
для указателя является префиксом) пару круглых скобок для привязки *
к имени вместо возвращаемого типа. Например, int *foo(int)
будет означать функцию с именем foo, которая принимает параметр int и возвращает указатель на int. Чтобы получить привязку * к foo
, нам нужны скобки, дающие int (*foo)(int)
.
Это становится особенно уродливым, когда вам нужен массив указателей на функции. В этом случае большинству людей проще всего использовать typedef для типа указателя, а затем создать массив этого типа:
typedef int (*fptr)(int);
fptr array[10];
Ответ 4
Я видел в некоторых местах указатели на функции, объявленные как
int (*foo) (int a, int b);
а в некоторых местах a
и b
не упоминаются, и оба все еще работают.
так
int (*foo) (int, int)
также правильно.
Очень простой способ, который я запомнил, как указано ниже:
Предположим, что функция объявлена как:
int function (int a , int b);
Шаг 1: Просто поместите функцию в скобках:
int (function) (int a , int b);
Step2: Поместите *
перед именем функции и измените имя:
int (*funcPntr) (int a , int b);
PS. В этом ответе я не соблюдаю надлежащие правила кодирования для соглашений об именах и т.д.