跳转到内容

C 语言指针数组

来自代码酷

C语言指针数组[编辑 | 编辑源代码]

指针数组是C语言中一种特殊的数组类型,其元素均为指针。这种数据结构在需要管理多个指针时非常有用,特别是在处理字符串数组、动态内存分配和多维数组模拟等场景中。

基本概念[编辑 | 编辑源代码]

指针数组的定义形式为:

数据类型 *数组名[数组长度];

其中:

  • 数据类型:指针所指向的数据类型
  • 数组名:指针数组的名称
  • 数组长度:数组中指针的数量

graph LR A[指针数组] --> B[指针1] A --> C[指针2] A --> D[...] A --> E[指针N] B --> F[数据1] C --> G[数据2] E --> H[数据N]

基本示例[编辑 | 编辑源代码]

下面是一个简单的指针数组示例,存储多个整数的地址:

#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 30;
    int *ptr_arr[3];  // 声明一个包含3个int指针的数组
    
    ptr_arr[0] = &a;
    ptr_arr[1] = &b;
    ptr_arr[2] = &c;
    
    for(int i = 0; i < 3; i++) {
        printf("ptr_arr[%d] = %p, *ptr_arr[%d] = %d\n", 
               i, ptr_arr[i], i, *ptr_arr[i]);
    }
    
    return 0;
}

输出示例

ptr_arr[0] = 0x7ffd4a3b5a1c, *ptr_arr[0] = 10
ptr_arr[1] = 0x7ffd4a3b5a20, *ptr_arr[1] = 20
ptr_arr[2] = 0x7ffd4a3b5a24, *ptr_arr[2] = 30

字符串指针数组[编辑 | 编辑源代码]

指针数组最常见的应用之一是存储字符串,因为字符串本身就是字符数组的指针:

#include <stdio.h>

int main() {
    char *names[] = {"Alice", "Bob", "Charlie", "David"};
    int count = sizeof(names)/sizeof(names[0]);
    
    for(int i = 0; i < count; i++) {
        printf("Name %d: %s\n", i+1, names[i]);
    }
    
    return 0;
}

输出

Name 1: Alice
Name 2: Bob
Name 3: Charlie
Name 4: David

指针数组与二维数组的区别[编辑 | 编辑源代码]

虽然指针数组可以模拟二维数组的行为,但它们有本质区别:

特性 指针数组 二维数组
内存布局 不连续 连续
每行长度 可以不同 必须相同
内存分配 可以动态分配 通常是静态分配

动态内存分配[编辑 | 编辑源代码]

指针数组常与动态内存分配结合使用:

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

int main() {
    int **matrix;
    int rows = 3, cols = 4;
    
    // 分配行指针
    matrix = (int **)malloc(rows * sizeof(int *));
    
    // 为每行分配列
    for(int i = 0; i < rows; i++) {
        matrix[i] = (int *)malloc(cols * sizeof(int));
    }
    
    // 初始化并打印
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
            printf("%2d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    // 释放内存
    for(int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);
    
    return 0;
}

输出

 0  1  2  3 
 4  5  6  7 
 8  9 10 11 

高级应用:函数指针数组[编辑 | 编辑源代码]

指针数组也可以存储函数指针,这在实现状态机或回调机制时非常有用:

#include <stdio.h>

void func1() { printf("Function 1 called\n"); }
void func2() { printf("Function 2 called\n"); }
void func3() { printf("Function 3 called\n"); }

int main() {
    void (*func_ptr_arr[])() = {func1, func2, func3};
    int choice;
    
    printf("Enter a number (1-3): ");
    scanf("%d", &choice);
    
    if(choice >= 1 && choice <= 3) {
        func_ptr_arr[choice-1]();
    } else {
        printf("Invalid choice\n");
    }
    
    return 0;
}

数学表示[编辑 | 编辑源代码]

指针数组可以表示为: P={p0,p1,...,pn1} 其中每个pi都是一个指针,满足: piP,pi:T T是目标数据类型。

实际应用场景[编辑 | 编辑源代码]

1. 命令行参数处理main(int argc, char *argv[])中的argv就是一个字符串指针数组 2. 菜单系统实现:存储菜单项及其对应的处理函数 3. 多态模拟:在C中模拟面向对象的多态行为 4. 稀疏矩阵存储:只存储非零元素的指针

常见错误与注意事项[编辑 | 编辑源代码]

1. 未初始化的指针数组元素可能导致段错误 2. 混淆指针数组和数组指针(int (*arr)[10] vs int *arr[10]) 3. 内存泄漏:动态分配的指针数组需要逐元素释放 4. 越界访问:与其他数组一样,指针数组也有边界限制

性能考虑[编辑 | 编辑源代码]

  • 访问时间:与普通数组相同,O(1)随机访问
  • 内存开销:需要额外存储指针本身
  • 缓存效率:指针间接寻址可能导致缓存不命中

通过理解指针数组的概念和应用,C程序员可以更灵活地处理复杂的数据结构和内存管理任务。