Синтаксис указателя функции C - программирование

Синтаксис указателя функции C

У меня очень простой вопрос.

Обычно при объявлении некоторой переменной перед ней ставится ее тип, например:

int a;

указатель на функцию может иметь тип, подобный следующему: int(*)(int,int), если мы указываем на функцию, которая принимает два целых числа и возвращает целое число. Но при объявлении такого указателя его идентификатор не соответствует типу, например:

int(*)(int,int) mypointer;

вместо этого вы должны написать идентификатор в середине:

int(*mypointer)(int,int);

почему это так? Извините, я знаю, это неловко простой вопрос...

Спасибо всем за ответ. КАК.

4b9b3361

Ответ 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. В этом ответе я не соблюдаю надлежащие правила кодирования для соглашений об именах и т.д.