通过函数指针调用函数-是否要解引用指针?有什么区别?

10

我尝试了 CC++,它们都可以正常工作。

我对函数指针还不太熟悉,这里有一个简单的代码,让我感到惊讶:

#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 );

两种方法都似乎能正常工作(没有错误、没有警告、排序后的数组),我有点困惑。哪一种是正确的,还是两种方法都正确?

Both seems to work (no errors, no warnings, sorted arrays) and I'm kinda confused. Which one is the correct one or they both are correct?

2个回答

17
sort_ptr( arr1, 5 );

(*sort_ptr)( arr2, 5 );

两种都是正确的。事实上,你可以放任意数量的星号,它们都是正确的:

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

函数名会衰变成一个指向函数的指针,因此重复对其进行解引用将产生相同的指针。


哇,这对我来说真的很奇怪。为什么语言会允许这样做呢?好吧,我可以使用一个 * - 可能是某种显式/隐式解引用(正如@Als在他的答案中所说),但为什么要允许那么多 * 呢? - Kiril Kirov
7
因为在形式上,调用一个函数需要一个指向函数的指针,而函数可以隐式地转换为指向函数的指针。每次添加一个 *,结果是一个函数,它会转换为指向函数的指针,这允许进一步的 * 操作。 - James Kanze

2
就编译器而言,sort_ptr(*sort_ptr)是相同的。然而,如果sort_ptr确实是一个指针,明确地对其进行解引用可以让读者更清楚地理解代码。通常情况下,在模板中直接调用函数指针非常有用,这样可以将函数指针作为一个函数对象使用,其行为与具有operator()()的类完全相同。请注意保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接