安守天命 發表於 2025-4-20 18:32:00

函数指针与指针函数的区别

<p>1. 函数指针</p>
<p><code>首先,它是一个指针,这个指针指向一个函数,或者说这个指针存放着函数的地址</code></p>
<pre class="language-cpp highlighter-hljs"><code>#include &lt;iostream&gt;

// 声明函数
int add(int x, int y);


// 定义函数
int add(int x, int y)
{
    return x + y;
}


int main()
{
    // 将函数指针ptr指向函数add,或者说将函数add的地址赋给函数指针ptr,此时称:指针指向一个函数
    int (*ptr)(int, int) = &amp;add;
   
    // 通过指针ptr,来调用函数,相当于int result = add(7, 8);
    // 通过函数指针ptr来使用函数,函数的返回值与直接调用add函数相同,所以返回值可直接赋值给result
    int result = ptr(7, 8);
   
    // 输出result的值
    std::cout &lt;&lt; "result: " &lt;&lt; result &lt;&lt; std::endl;

    return 0;
}</code></pre>
<p><strong>函数指针的语法:int (*ptr)(int, int)</strong></p>
<p><strong>*ptr必须被括号括起来,否则不是函数指针</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>2. 指针函数</p>
<p><code>首先,它是一个函数,这个函数的返回值是一个指针,即return时,是return一个地址到函数的调用处</code></p>
<pre class="language-cpp highlighter-hljs"><code>#include &lt;iostream&gt;

// 声明指针函数
int *add(int x, int y);


// 定义指针函数
int *add(int x, int y)
{
    /**
   * 单独出现的int(x + y)会执行强制类型转换比如int a = int(x + y)
   * 但在new int(x + y)中,它是初始化语法,两者语义不同
   */

    // 在堆上分配内存
    int *sum = new int(x + y);

    // 返回堆内存地址
    return sum;
}


int main()
{   
    // 将调用add指针函数返回的地址赋给指针变量result
    int *result = add(7, 8);
   
    // 解引用result指针变量,得到值进行输出
    std::cout &lt;&lt; "result: " &lt;&lt; *result &lt;&lt; std::endl;

    // 必须手动释放内存
    delete result;

    return 0;
}</code></pre>
<p>&nbsp;</p>
<p><strong>C语言实现:</strong></p>
<pre class="language-c highlighter-hljs"><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

// 声明指针函数
int *add(int x, int y);

// 定义指针函数
int *add(int x, int y)
{
    // 使用malloc在堆上分配内存
    int *sum = (int*)malloc(sizeof(int));

    /**
   * stdout(对应printf)通常是行缓冲的​
   * 意味着当遇到换行符\n或缓冲区满时才会输出内容,如果程序崩溃,未刷新的缓冲区内容可能丢失
   *
   * stderr(对应fprintf)默认无缓冲​
   * 错误信息会​​立即输出​​,即使程序中途崩溃,也能确保错误信息被及时显示,调试时很有用
   */
   
    // 检查内存分配是否成功
    if (sum == NULL) {
      // 使用fprintf将信息输出到​标准错误流stderr,而不是printf的标准输出流stdout
      fprintf(stderr, "Memory allocation failed\n");
      exit(EXIT_FAILURE);
    }
   
    // 将计算结果存入分配的内存中
    *sum = x + y;
   
    return sum;
}

int main()
{
    // 调用函数获取堆内存地址
    int *result = add(7, 8);
   
    // 输出结果
    printf("result: %d\n", *result);
   
    // 释放堆内存
    free(result);
   
    return 0;
}</code></pre>
<p>&nbsp;</p>
<p><strong>典型的错误使用方式:</strong></p>
<pre class="language-cpp highlighter-hljs"><code>#include &lt;iostream&gt;

// 声明指针函数
int *add(int x, int y);


// 定义指针函数
int *add(int x, int y)
{
    // sum是局部变量,存储在栈上
    int sum = x + y;
    // 将指针ptr指向变量sum,或者说将变量sum的地址赋给ptr
    int *ptr = &amp;sum;
   
   
    /**
   * 函数返回后, sum的内存会被回收,ptr成为悬垂指针
   * 悬垂指针:一个指向了无效的内存地址的指针
   * 由于add函数结束后,sum变量所在的内存空间已经被释放
   * 释放了内存之后,指针还指向原来的地址,这时候那个地址已经被系统回收了
   * 被回收的地址所指向的变量以及变量的值也已经失效了
   * 如果进行访问,就会出现问题
   */
   
    return ptr;
}


int main()
{
    /**
   * 当add()函数执行完毕时,栈帧被销毁,sum的内存被回收
   * 此时result指针指向的是已被释放的内存,
   * 访问*result会导致未定义行为,可能输出错误的值,程序崩溃或输出看似正常但存在隐患
   */
   
    // 调用add指针函数,会返回一个地址,赋给指针变量result
    int *result = add(7, 8);
    // 解引用result,结果理论上输出15,但实际可能存在错误隐患
    std::cout &lt;&lt; "result: " &lt;&lt; *result &lt;&lt; std::endl;

    return 0;
}</code></pre>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/Rinato/p/18837206
頁: [1]
查看完整版本: 函数指针与指针函数的区别