C语言指针与函数 #

一、指针作为函数参数 #

1.1 基本用法 #

c
#include <stdio.h>

void modify(int* p) {
    *p = 100;
}

int main() {
    int a = 10;
    printf("修改前: %d\n", a);
    modify(&a);
    printf("修改后: %d\n", a);
    return 0;
}

输出:

text
修改前: 10
修改后: 100

1.2 交换两个数 #

c
#include <stdio.h>

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 10, y = 20;
    printf("交换前: x=%d, y=%d\n", x, y);
    swap(&x, &y);
    printf("交换后: x=%d, y=%d\n", x, y);
    return 0;
}

1.3 为什么需要指针参数 #

C语言是值传递,指针参数可以:

  • 修改调用者的变量
  • 避免复制大数据
  • 返回多个值

1.4 返回多个值 #

c
#include <stdio.h>

void min_max(int arr[], int size, int* min, int* max) {
    *min = arr[0];
    *max = arr[0];
    
    for (int i = 1; i < size; i++) {
        if (arr[i] < *min) *min = arr[i];
        if (arr[i] > *max) *max = arr[i];
    }
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6};
    int min_val, max_val;
    
    min_max(arr, 8, &min_val, &max_val);
    printf("最小值: %d, 最大值: %d\n", min_val, max_val);
    return 0;
}

二、数组作为函数参数 #

2.1 一维数组 #

c
#include <stdio.h>

int sum(int arr[], int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    printf("总和: %d\n", sum(arr, 5));
    return 0;
}

等价写法:

c
int sum(int* arr, int size);

2.2 指针范围参数 #

c
#include <stdio.h>

int sum(int* start, int* end) {
    int total = 0;
    while (start < end) {
        total += *start++;
    }
    return total;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    printf("总和: %d\n", sum(arr, arr + 5));
    return 0;
}

2.3 二维数组 #

c
#include <stdio.h>

void print_matrix(int rows, int cols, int mat[rows][cols]) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%2d ", mat[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    print_matrix(3, 4, matrix);
    return 0;
}

2.4 使用行指针 #

c
#include <stdio.h>

void print_matrix(int (*mat)[4], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%2d ", mat[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    print_matrix(matrix, 3);
    return 0;
}

三、返回指针的函数 #

3.1 基本用法 #

c
#include <stdio.h>

int* find_max(int arr[], int size) {
    int* max = arr;
    for (int i = 1; i < size; i++) {
        if (arr[i] > *max) {
            max = &arr[i];
        }
    }
    return max;
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6};
    int* max = find_max(arr, 8);
    printf("最大值: %d\n", *max);
    return 0;
}

3.2 返回动态分配内存 #

c
#include <stdio.h>
#include <stdlib.h>

int* create_array(int size) {
    int* arr = (int*)malloc(size * sizeof(int));
    if (arr == NULL) {
        return NULL;
    }
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }
    return arr;
}

int main() {
    int* arr = create_array(5);
    if (arr != NULL) {
        for (int i = 0; i < 5; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
        free(arr);
    }
    return 0;
}

3.3 不要返回局部变量地址 #

c
int* bad_func() {
    int local = 10;
    return &local;
}

错误:函数返回后,局部变量被销毁。

3.4 返回静态变量地址 #

c
#include <stdio.h>

int* get_counter() {
    static int count = 0;
    count++;
    return &count;
}

int main() {
    printf("%d\n", *get_counter());
    printf("%d\n", *get_counter());
    printf("%d\n", *get_counter());
    return 0;
}

四、函数指针 #

4.1 声明函数指针 #

c
int (*func_ptr)(int, int);

这是一个指向 int (int, int) 类型函数的指针。

4.2 使用函数指针 #

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 (*op)(int, int);
    
    op = add;
    printf("10 + 5 = %d\n", op(10, 5));
    
    op = subtract;
    printf("10 - 5 = %d\n", op(10, 5));
    return 0;
}

4.3 函数指针数组 #

c
#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }

int main() {
    int (*operations[])(int, int) = {add, subtract, multiply, divide};
    char* names[] = {"加", "减", "乘", "除"};
    
    int a = 20, b = 5;
    for (int i = 0; i < 4; i++) {
        printf("%d %s %d = %d\n", a, names[i], b, operations[i](a, b));
    }
    return 0;
}

4.4 回调函数 #

c
#include <stdio.h>
#include <stdlib.h>

int compare_asc(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

int compare_desc(const void* a, const void* b) {
    return (*(int*)b - *(int*)a);
}

void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    qsort(arr, size, sizeof(int), compare_asc);
    printf("升序: ");
    print_array(arr, size);
    
    qsort(arr, size, sizeof(int), compare_desc);
    printf("降序: ");
    print_array(arr, size);
    return 0;
}

4.5 高阶函数 #

c
#include <stdio.h>

void process_array(int arr[], int size, int (*processor)(int)) {
    for (int i = 0; i < size; i++) {
        arr[i] = processor(arr[i]);
    }
}

int double_it(int x) { return x * 2; }
int square_it(int x) { return x * x; }

void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr1[] = {1, 2, 3, 4, 5};
    int arr2[] = {1, 2, 3, 4, 5};
    int size = 5;
    
    process_array(arr1, size, double_it);
    printf("翻倍: ");
    print_array(arr1, size);
    
    process_array(arr2, size, square_it);
    printf("平方: ");
    print_array(arr2, size);
    return 0;
}

五、const与指针参数 #

5.1 保护数据不被修改 #

c
#include <stdio.h>

int sum(const int* arr, int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    printf("总和: %d\n", sum(arr, 5));
    return 0;
}

5.2 字符串参数 #

c
#include <stdio.h>
#include <string.h>

size_t safe_strlen(const char* str) {
    return strlen(str);
}

int main() {
    const char* msg = "Hello";
    printf("长度: %zu\n", safe_strlen(msg));
    return 0;
}

六、实战应用 #

6.1 通用排序 #

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[20];
    int age;
} Person;

int compare_by_age(const void* a, const void* b) {
    return ((Person*)a)->age - ((Person*)b)->age;
}

int compare_by_name(const void* a, const void* b) {
    return strcmp(((Person*)a)->name, ((Person*)b)->name);
}

int main() {
    Person people[] = {
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 30}
    };
    int size = 3;
    
    qsort(people, size, sizeof(Person), compare_by_age);
    printf("按年龄排序:\n");
    for (int i = 0; i < size; i++) {
        printf("%s: %d\n", people[i].name, people[i].age);
    }
    
    qsort(people, size, sizeof(Person), compare_by_name);
    printf("\n按姓名排序:\n");
    for (int i = 0; i < size; i++) {
        printf("%s: %d\n", people[i].name, people[i].age);
    }
    return 0;
}

6.2 策略模式 #

c
#include <stdio.h>

typedef int (*Strategy)(int, int);

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }

int calculate(int a, int b, Strategy strategy) {
    return strategy(a, b);
}

int main() {
    printf("10 + 5 = %d\n", calculate(10, 5, add));
    printf("10 - 5 = %d\n", calculate(10, 5, subtract));
    printf("10 * 5 = %d\n", calculate(10, 5, multiply));
    return 0;
}

七、总结 #

指针参数 #

用途 说明
修改调用者变量 传递地址
避免复制大数据 传递指针
返回多个值 指针参数

返回指针 #

  • 可以返回动态分配的内存
  • 可以返回静态变量地址
  • 不能返回局部变量地址

函数指针 #

c
int (*func_ptr)(int, int);

用于回调函数、策略模式等。

const保护 #

c
void func(const int* p);

防止函数修改数据。

下一步,让我们学习函数指针!

最后更新:2026-03-26