Є кілька деталей, які дозволяють всім цим комбінаціям операторів працювати однаково.
Основною причиною, чому всі ці роботи є, є те, що функція (як 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, як і слід було очікувати.