Є кілька деталей, які дозволяють всім цим комбінаціям операторів працювати однаково.
Основною причиною, чому всі ці роботи є, є те, що функція (як foo
) неявно конвертується у покажчик на функцію. Ось чому void (*p1_foo)() = foo;
працює: foo
неявно перетворюється на вказівник на себе і йому вказуєтьсяp1_foo
.
Унарний &
, застосовуваний до функції, видає покажчик на функцію, як і адресу об'єкта, коли він застосовується до об'єкта. Для покажчиків на звичайні функції він завжди є надлишковим через неявне перетворення функції в функцію-покажчик. У будь-якому випадку, саме тому void (*p3_foo)() = &foo;
працює.
Унарний *
, застосовуваний до покажчика на функцію, дає функцію, на яку спрямовано, так само, як і об'єкт, на яку спрямовано, коли він застосовується до звичайного покажчика на об'єкт.
Ці правила можна поєднувати. Розглянемо ваш останній і останній приклад **foo
:
- По-перше,
foo
неявно перетворюється на покажчик на себе, а перший *
застосовується до цього покажчика функції, що foo
знову дає функцію .
- Потім результат знову неявно перетворюється на покажчик на себе і застосовується другий
*
, знову отримуючи функціюfoo
.
- Потім він неявно перетворюється на покажчик функції знову і присвоюється змінній.
Ви можете додати скільки *
завгодно s, результат завжди однаковий. Більше*
s, тим веселіше.
Ми також можемо розглянути ваш п'ятий приклад &*foo
:
- По-перше,
foo
неявно перетворюється на покажчик на себе; одинарний *
застосовується, поступаючисьfoo
знову .
- Потім, значення
&
застосовується до foo
, отримуючи покажчик на foo
, який присвоюється змінній.
Однак &
функцію can можна застосувати лише до функції, але не до функції, яка була перетворена на покажчик функції (якщо, звичайно, покажчик функції не є змінною, в цьому випадку результатом є покажчик на вказівник на to-a-function; наприклад, ви можете додати до свого списку void (**pp_foo)() = &p7_foo;
).
Ось чому &&foo
не працює: &foo
не є функцією; це покажчик функції, який є значенням r. Однак &*&*&*&*&*&*foo
це спрацювало б, як би &******&foo
, оскільки в обох цих виразах значення &
завжди застосовується до функції, а не до покажчика функції rvalue.
Зауважте також, що *
для здійснення виклику за допомогою покажчика на функцію не потрібно використовувати одинарне ; обидва (*p1_foo)();
і (p1_foo)();
мають однаковий результат, знову ж таки через перетворення покажчика функція на функцію.
&foo
приймає адресуfoo
, в результаті чого вказівник на функцію вказуєfoo
, як і слід було очікувати.