Вызов функции через указатель на функцию-разыменование указателя или нет? Какая разница?

Я пытался как - C и C++ и оба прекрасно работают.

Я вроде как новичок в указателях функций, и вот простой код, который меня удивил:

#include <assert.h>
void sort( int* arr, const int N );

int main () 
{
    int arr1[] = { 1, 5, 2, 6, 2 }; 
    int arr2[] = { 1, 5, 2, 6, 2 }; 

    void (*sort_ptr)( int*,  const int) = sort;

    sort_ptr( arr1, 5 );
    (*sort_ptr)( arr2, 5 );

    assert( arr1[0] == 1 && arr1[1] == 2 && arr1[2] == 2 && 
            arr1[3] == 5 && arr1[4] == 6 );
    assert( arr2[0] == 1 && arr2[1] == 2 && arr2[2] == 2 && 
            arr2[3] == 5 && arr2[4] == 6 );

    return 0;
}

void sort( int* arr, const int N )
{
    // sorting the array, it's not relevant to the question
}

Итак, в чем разница между

sort_ptr( arr1, 5 );

и

(*sort_ptr)( arr2, 5 );

оба, кажется, работают (без ошибок, без предупреждений, отсортированных массивов), и я немного запутался. Какой правильный или они оба верны?

2 ответов


sort_ptr( arr1, 5 );

и

(*sort_ptr)( arr2, 5 );

оба правы. На самом деле, вы можете поставить столько звездочек, сколько хотите, и все они правильные:

(*****sort_ptr)( arr2, 5 );

имя функции распадается на указатель на функцию. Таким образом, разыменование его повторно приведет к созданию одного и того же указателя.


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