Логика вызова функции с использованием указателя на функцию

Предположим, что есть указатель f, объявленный на некоторую функцию, скажем, int foo(int) как:

int (*f)(int)=foo;

При упоминании о вызове функции foo() с помощью этого понтера, который передается в качестве аргумента какой-либо другой функции. Я наткнулся на заявление о том, что оба

y=(*f)(x) и

y=f(x)

одинаковы в C и вызывает функцию foo()....(x и y имеют тип int).

Для массивов я знаю, что если p является указателем на любой массив a.

p[i]=*(p+i)=*(&a[0]+i)=*(a+i)=a[i].

Так что писать p[i] и *(p+i) — одно и то же. Но я не понимаю логики для случая «указатель на функцию». Чем отличаются y=(*f)(x) и y=f(x)? Есть ли какая-нибудь формула, чтобы понять это, как в случае «указателя на массивы»?


person Avi    schedule 02.03.2019    source источник
comment
Чтобы понять это, не требуется формулы.   -  person machine_1    schedule 02.03.2019
comment
Так это просто правило, которое я должен помнить?   -  person Avi    schedule 02.03.2019
comment
Проект стандарта C11 n1570: 6.5.3.2 Операторы адреса и косвенности 4 Унарный оператор * обозначает косвенность. Если операнд указывает на функцию, результатом является указатель функции [...] 6.3 Преобразования 6.3.2 Другие операнды 6.3.2.1 Lзначения, массивы и указатели функций 4 Указатель функции — это выражение, имеющее функциональный тип. За исключением случаев, когда это операнд оператора sizeof, оператора _Alignof, 65) или унарного оператора &, указатель функции с типом ''функция, возвращающая тип'' преобразуется в выражение, имеющее тип ''указатель на функцию, возвращающую тип ''.   -  person EOF    schedule 02.03.2019
comment
@Someprogrammerdude Как показывает моя стандартная цитата, у вас это наоборот. Указатель функции перед вызовом преобразуется в pointer to function. См. n1570: 6.5.2.2 Вызовы функций 1 Выражение, обозначающее вызываемую функцию 92), должно иметь указатель типа на функцию, возвращающую void или возвращающую полный тип объекта, отличный от типа массива.   -  person EOF    schedule 02.03.2019


Ответы (1)


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

Когда C стал стандартизированным, люди поняли, что с указателем на функцию мало что можно сделать, кроме как вызвать его (арифметика указателей не имеет смысла для указателей на функции - указатели на функции указывают на блоки ассемблерных инструкций, длина которых зависит на конкретной функции, а не на типе функций. Это также причина, по которой вы не можете иметь массивы функций), поэтому f(x) был сделан эквивалентным (*f)(x) (или даже (****f)(x) или (**&**f)(x) и различным другим комбинациям), пока f является либо функция или одиночные косвенные указатели на функции (если это указатель на указатель на функцию, вам нужен хотя бы один * и т. д. для множественных косвенных указателей).

person PSkocik    schedule 02.03.2019