Я не могу придумать никакого практического использования нескольких звездочек в вызове функции:
void foo(int a, char b)
{
}
int main(void)
{
(**************foo)(45, 'c');
//or with pointer to function:
void (*ptr)(int, char) = foo;
(******ptr)(32, 'a');
}
Почему эта штука разрешена и в C, и в C++?
Одним из стандартных преобразований, как в C, так и в C++, является преобразование функции в указатель; когда имя функции появляется в выражении, оно может быть преобразовано в указатель на эту функцию. Таким образом:
foo
эквивалентно &foo
.*foo
эквивалентно *(&foo)
, или foo
.**foo
эквивалентен **(&foo)
, или *foo
, или foo
.и так далее.
Это означает, что вы можете легально добавлять сколько угодно *
перед именем функции без изменения ее смысла. Однако нет никаких причин делать это.
Почему эта штука разрешена и в C, и в C++?
Я не могу говорить за C++, но в C, по крайней мере, обозначение функции преобразуется в указатель:
6.3.2.1 - 4
указатель функции - это выражение, которое имеет тип функции. За исключением когда он является операндом оператора sizeof или унарного оператора &, обозначение функции с типом ''функция, возвращающая тип'' преобразуется в выражение, имеющее тип ''указатель на функцию возвращающей тип''.
Применение оператора перенаправления дает обозначение функции:
6.5.3.2 - 3
Унарный оператор * обозначает перенаправление. Если операнд указывает на функцию, результатом будет указатель функции.
Поэтому, сколько бы раз вы ни применяли оператор перенаправления, вы получите одно и то же: обозначение функции, которое немедленно преобразуется в указатель.
На мой взгляд, в этом нет практически никакой пользы.
Потому что оператор *
ожидает значение адреса. А когда ожидается значение (в отличие от значения объекта или функции), к операнду применяются преобразования lvalue to rvalue, function to pointer и array to pointer. Таким образом, разыменованная функция при повторном разыменовании немедленно преобразуется в указатель.
Все они либо считывают значения из объектов, либо создают значение указателя, которое ссылается на начало массива или функции соответственно.
Эти ряды разыменований не имеют никакой цели, кроме как для смеха.
Как я понимаю это
* is a pointer to a memory address
& is the value at the Memory address
*foo means pointer to foo memory address
**foo means *(*foo) *(foo memory address) This is a different value from *foo
так продолжается...