当前位置: 首页 > article >正文

C语言——指针进阶应用

引言

在掌握了指针的基础知识后,我们可以进一步探索指针在 C 语言中的高级应用。指针的灵活性和强大功能使其在复杂数据结构、函数指针、动态内存管理等领域大放异彩。本文将深入探讨指针的进阶用法,包括多级指针、函数指针、指针数组、动态内存分配的高级技巧,以及如何避免常见的指针陷阱。通过实际代码示例,帮助你从“会用指针”进阶到“精通指针”。


一、多级指针

1. 二级指针

二级指针是指向指针的指针,常用于动态分配二维数组或修改指针本身的值。

示例:动态分配二维数组
int **arr;
int rows = 3, cols = 4;

// 分配行指针
arr = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
    // 为每行分配列
    arr[i] = (int *)malloc(cols * sizeof(int));
}

// 使用二维数组
arr[1][2] = 10;  // 第2行第3列赋值为10

// 释放内存
for (int i = 0; i < rows; i++) {
    free(arr[i]);
}
free(arr);

2. 三级指针

三级指针是指向二级指针的指针,常用于动态分配三维数组或更复杂的数据结构。

示例:动态分配三维数组
int ***arr;
int x = 2, y = 3, z = 4;

// 分配第一维
arr = (int ***)malloc(x * sizeof(int **));
for (int i = 0; i < x; i++) {
    // 分配第二维
    arr[i] = (int **)malloc(y * sizeof(int *));
    for (int j = 0; j < y; j++) {
        // 分配第三维
        arr[i][j] = (int *)malloc(z * sizeof(int));
    }
}

// 使用三维数组
arr[1][2][3] = 20;  // 第2层第3行第4列赋值为20

// 释放内存
for (int i = 0; i < x; i++) {
    for (int j = 0; j < y; j++) {
        free(arr[i][j]);
    }
    free(arr[i]);
}
free(arr);

 

二、函数指针

函数指针是指向函数的指针,常用于回调函数、动态函数调用等场景。

1. 函数指针的声明与使用

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

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

int main() {
    // 声明函数指针
    int (*func_ptr)(int, int);

    // 指向 add 函数
    func_ptr = add;
    printf("Add: %d\n", func_ptr(5, 3));  // 输出 8

    // 指向 subtract 函数
    func_ptr = subtract;
    printf("Subtract: %d\n", func_ptr(5, 3));  // 输出 2

    return 0;
}

2. 回调函数

回调函数是通过函数指针实现的,常用于事件驱动编程。

示例:排序算法中的回调
#include <stdio.h>
#include <stdlib.h>

// 回调函数类型
typedef int (*compare_func)(int, int);

// 回调函数:升序比较
int ascending(int a, int b) {
    return a - b;
}

// 回调函数:降序比较
int descending(int a, int b) {
    return b - a;
}

// 通用排序函数
void sort(int *arr, int size, compare_func cmp) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = i + 1; j < size; j++) {
            if (cmp(arr[i], arr[j]) > 0) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

int main() {
    int arr[] = {5, 2, 9, 1, 5, 6};
    int size = sizeof(arr) / sizeof(arr[0]);

    // 升序排序
    sort(arr, size, ascending);
    printf("Ascending: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 降序排序
    sort(arr, size, descending);
    printf("Descending: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

 

三、指针数组与数组指针

1. 指针数组

指针数组是元素为指针的数组,常用于存储字符串数组。

示例:字符串数组
char *fruits[] = {"Apple", "Banana", "Cherry"};
for (int i = 0; i < 3; i++) {
    printf("%s\n", fruits[i]);
}

2. 数组指针

数组指针是指向数组的指针,常用于传递多维数组。

示例:传递二维数组
void print_matrix(int (*arr)[3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    print_matrix(matrix, 2);
    return 0;
}

四、动态内存分配的高级技巧

1. 柔性数组(Flexible Array Member)

柔性数组是结构体中最后一个成员,用于动态分配额外空间。

示例:动态字符串结构
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct flex_string {
    int length;
    char data[];  // 柔性数组
};

int main() {
    char str[] = "Hello, World!";
    int length = strlen(str);

    // 分配内存
    struct flex_string *fs = malloc(sizeof(struct flex_string) + length + 1);
    fs->length = length;
    strcpy(fs->data, str);

    printf("Length: %d\n", fs->length);
    printf("Data: %s\n", fs->data);

    free(fs);
    return 0;
}

2. 内存池(Memory Pool)

内存池是一种高效的内存管理技术,适用于频繁分配和释放小块内存的场景。


五、总结

指针的进阶应用是 C 语言编程的核心技能之一。通过掌握多级指针、函数指针、指针数组等高级特性,你可以编写出更高效、更灵活的代码。同时,动态内存管理的高级技巧(如柔性数组和内存池)能显著提升程序的性能和稳定性。


参考资料

  1. 《C和指针》 - Kenneth A.Reek

  2. 《C专家编程》 - Peter van der Linden

  3. GeeksforGeeks: Function Pointer in C


如果你对指针的某个高级用法有疑问,欢迎在评论区留言讨论!


http://www.kler.cn/a/551727.html

相关文章:

  • 利用分治策略优化快速排序
  • 2013年下半年软件设计师上午题考察知识点及其详细解释(附真题及答案解析)
  • MAVEN学习
  • 使用brew install python,跟 Mac自带的python版本会发生冲突吗?
  • 【数据结构】(10) 排序算法
  • 《Python实战进阶》专栏 No2: Flask 中间件与请求钩子的应用
  • Gurobi重新激活
  • redis群集-简单部署
  • 【JavaScript】正则表达式综合案例
  • Jenkins 调用 Shell 脚本,在Shell脚本中调用 Unity 类方法,传递参数给Unity
  • 如何在Odoo 18中创建记录规则Rule
  • 芯麦 GC1808:高性能、低成本的立体声音频模数转换器
  • Firecrawl的docker部署巨坑(逐一击破)
  • Linux-GlusterFS进阶配置
  • 网络安全等级保护测评(等保测评):全面指南与准备要点
  • 【Javascript Day18】
  • RK3568平台开发系列讲解(PWM篇)SG90 舵机驱动实验
  • 什么是电力交易员
  • 《Java 排序算法新视界:八大排序算法全解析》
  • 网工_IP地址