C语言高频面试题——指针函数和函数指针的区别

在 C 语言中,指针函数函数指针 是两个容易混淆的概念,但它们的功能和用途完全不同。以下是详细的对比分析,帮助你彻底理解它们的区别。


1. 指针函数(Function Returning a Pointer)

定义
  • 指针函数 是一个返回值为指针类型的函数。
  • 它本质上是一个普通函数,只是其返回值是指向某种数据类型的指针。
语法
c 复制代码
type* functionName(parameters);
  • type*:返回值类型是指针。
  • functionName:函数名。
  • parameters:函数的参数列表。
特点
  1. 返回值是一个指针。
  2. 可以通过返回的指针访问或修改内存中的数据。
  3. 常用于动态内存分配、字符串操作等场景。
示例
c 复制代码
#include <stdio.h>

// 指针函数:返回一个指向整型的指针
int* getMaxPointer(int* a, int* b) {
    return (*a > *b) ? a : b;
}

int main() {
    int x = 10, y = 20;
    int* ptr = getMaxPointer(&x, &y); // 返回指向较大值的指针
    printf("Max value: %d\n", *ptr);  // 输出 20
    return 0;
}
使用场景
  • 动态分配内存并返回指针:

    c 复制代码
    int* allocateMemory(int size) {
        return malloc(size * sizeof(int));
    }
  • 返回数组或字符串的一部分:

    c 复制代码
    char* getSubstring(char* str, int start, int len) {
        char* result = malloc(len + 1);
        strncpy(result, str + start, len);
        result[len] = '\0';
        return result;
    }

2. 函数指针(Pointer to Function)

定义
  • 函数指针 是一个指向函数的指针变量。
  • 它存储的是函数的入口地址,可以通过函数指针调用对应的函数。
语法
c 复制代码
return_type (*pointer_name)(parameter_types);
  • return_type:函数的返回值类型。
  • (*pointer_name):函数指针的名称。
  • parameter_types:函数的参数类型列表。
特点
  1. 存储的是函数的地址。
  2. 可以通过函数指针调用函数。
  3. 常用于回调函数、函数表、动态选择函数等场景。
示例
c 复制代码
#include <stdio.h>

// 两个简单的函数
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 定义函数指针
    int (*operation)(int, int);

    // 将函数指针指向不同的函数
    operation = add;
    printf("Add: %d\n", operation(5, 3)); // 输出 8

    operation = subtract;
    printf("Subtract: %d\n", operation(5, 3)); // 输出 2

    return 0;
}
使用场景
  • 回调函数:

    c 复制代码
    void execute(int (*callback)(int, int), int a, int b) {
        printf("Result: %d\n", callback(a, b));
    }
    
    int multiply(int a, int b) {
        return a * b;
    }
    
    int main() {
        execute(multiply, 4, 5); // 输出 20
        return 0;
    }
  • 函数表(如状态机实现):

    c 复制代码
    int add(int a, int b) { return a + b; }
    int subtract(int a, int b) { return a - b; }
    
    int main() {
        int (*operations[2])(int, int) = {add, subtract};
        printf("Add: %d\n", operations[0](5, 3));       // 输出 8
        printf("Subtract: %d\n", operations[1](5, 3)); // 输出 2
        return 0;
    }

3. 核心区别总结

特性 指针函数 函数指针
定义 返回值为指针的函数 指向函数的指针变量
语法 type* functionName(parameters) return_type (*pointer_name)(parameters)
本质 普通函数,返回指针 存储函数地址,用于调用函数
使用场景 动态内存分配、返回复杂数据结构 回调函数、函数表、动态选择函数
示例 int* getMaxPointer(int* a, int* b) int (*operation)(int, int);

4. 示例对比

指针函数
c 复制代码
char* getString() {
    static char str[] = "Hello, World!";
    return str;
}

int main() {
    char* message = getString();
    printf("%s\n", message); // 输出 "Hello, World!"
    return 0;
}
函数指针
c 复制代码
void greet() {
    printf("Hello!\n");
}

int main() {
    void (*funcPtr)() = greet; // 函数指针指向 greet
    funcPtr(); // 调用 greet 函数
    return 0;
}

5. 注意事项

  1. 指针函数

    • 确保返回的指针有效(避免返回局部变量的地址)。

    • 示例错误:

      c 复制代码
      char* getString() {
          char str[] = "Hello"; // 局部变量
          return str; // 错误:返回悬空指针
      }
  2. 函数指针

    • 确保函数指针与目标函数的签名匹配。

    • 示例错误:

      c 复制代码
      int add(int a, int b) { return a + b; }
      void (*funcPtr)() = add; // 错误:签名不匹配

6. 总结

  • 指针函数:一个返回指针的函数,重点在于返回值。
  • 函数指针:一个指向函数的指针变量,重点在于调用函数。
相关推荐
_一条咸鱼_5 小时前
深度剖析:Android NestedScrollView 惯性滑动原理大揭秘
android·面试·android jetpack
_一条咸鱼_5 小时前
深度揭秘!Android NestedScrollView 绘制原理全解析
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘 Android CoordinatorLayout:从源码深度解析其协同工作原理
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘 Android View 的 TranslationY 位移原理:源码深度剖析
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘 Android NestedScrollView 滑动原理:源码深度剖析
android·面试·android jetpack
_一条咸鱼_5 小时前
深度揭秘:Android NestedScrollView 拖动原理全解析
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘!Android RecyclerView 预取(Prefetch)原理深度剖析
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘 Android ImageView:从源码深度剖析使用原理
android·面试·android jetpack
_一条咸鱼_5 小时前
深入剖析 Android AppBarLayout:从源码洞悉其工作原理
android·面试·android jetpack
_一条咸鱼_5 小时前
揭秘!Android NestedScrollView 布局原理深度剖析
android·面试·android jetpack