C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C语言 指针数组和数组指针

C语言中指针数组和数组指针的具体使用

作者:VekiSon

指针数组和数组指针是C语言中高频混淆的概念,它们在语法和用途上有显著区别,指针数组中的每个元素都是指针,而数组指针指向一个完整的数组,下面就来详细的介绍一下

指针数组和数组指针是C语言中高频混淆的概念,核心区别在于本质不同

一、指针数组

一个普通数组,但其每个元素的类型是指针(可以指向 int、char、结构体等任意类型)。

1.语法格式

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

int *p[5];   // 指针数组:数组p有5个元素,每个元素是int*类型的指针
char *str[3];// 指针数组:数组str有3个元素,每个元素是char*类型的指针(常用于字符串)

关键:[ ] 优先级高于 *,所以 p 先与 [ ] 结合,确定是数组,再由 * 确定数组元素是指针。

2.常见用法

存储多个字符串(避免字符串数组的内存浪费)、指向多个一维数组

字符串常量的本质是字符数组的首地址,用 char * 指针数组存储这些地址,高效且灵活。

#include <stdio.h>

int main() {
    // 指针数组:每个元素指向一个字符串常量(首地址)
    char *fruit[] = {"apple", "banana", "cherry", "date"};
    int n = sizeof(fruit) / sizeof(fruit[0]); // 数组长度:4

    // 遍历指针数组,打印每个字符串
    for (int i = 0; i < n; i++)
    {
        // fruit[i] 是指针,指向字符串首地址,%s 直接解析
        printf("fruit[%d]: %s\n", i, fruit[i]);
    }

    return 0;
}

输出:

fruit[0]: apple

fruit[1]: banana

fruit[2]: cherry

fruit[3]: date

优势:字符串长度不同时,指针数组仅存储地址(4 字节 / 个),比 char fruit[4][20](固定 20 字节 / 个)节省内存。

#include <stdio.h>

int main() {
    int arr1[] = {1,2,3};
    int arr2[] = {4,5,6};
    int arr3[] = {7,8,9};

    // 指针数组:每个元素指向一个int型一维数组
    int *p_arr[] = {arr1, arr2, arr3}; 

    // 遍历:通过指针数组访问每个一维数组的元素
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            // p_arr[i] 是数组首地址,p_arr[i][j] 等价于 *(p_arr[i] + j)
            printf("%d ", p_arr[i][j]);
        }
        printf("\n");
    }

    return 0;
}

输出:

1 2 3

4 5 6

7 8 9

二、数组指针

一个指针变量,专门指向一个完整的数组(而非数组的单个元素)。

一维数组的数组名是指向第一个元素的指针。数组名+1,步进值是 sizeof(基类型) 的大小。

二维数组的数组名是指向第一行第一个元素的指针。数组名+1,步进值是一行的大小。

1.语法格式

数据类型 (*指针名)[数组长度];

int (*p)[5];   // 数组指针:p是指针,指向一个「int[5]类型」的数组
char (*q)[10]; // 数组指针:q是指针,指向一个「char[10]类型」的数组

关键:必须加括号 (),强制 p 先与 * 结合,确定是指针,再由 [5] 确定指向的数组类型(int [5])。

2.常见用法

指向二维数组作为函数参数接收二维数组(避免二维数组传参退化问题)。

#include <stdio.h>

int main() {
    // 二维数组:3个元素,每个元素是int[5]类型的一维数组
    int arr[3][5] = {{1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}};

    // 数组指针:p指向int[5]类型的数组(与二维数组的元素类型匹配)
    int (*p)[5] = arr; 

    // 遍历二维数组(3种等价写法)
    for (int i = 0; i < 3; i++) 
    {
        for (int j = 0; j < 5; j++) 
        {
            // 写法1:p[i][j](最直观,等价于二维数组访问)
            // 写法2:*(p[i] + j)(p[i]是第i个一维数组的首地址)
            // 写法3:*(*(p + i) + j)(p+i指向第i个一维数组)
            printf("%d ", *(*(p + i) + j));
        }
        printf("\n");
    }

    return 0;
}

输出:

1 2 3 4 5 

6 7 8 9 10 

11 12 13 14 15 

核心逻辑:arr 是二维数组首地址(指向 arr [0],即第一个 int [5] 数组),与数组指针 p 的类型完全匹配,因此 p = arr 合法。

#include <stdio.h>

// 函数参数:用数组指针接收二维数组(int[3][5]退化为int(*)[5])
void print2DArray(int (*p)[5], int row) 
{
    for (int i = 0; i < row; i++) 
    {
        for (int j = 0; j < 5; j++) 
        {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }
}

int main() 
{
    int arr[3][5] = {{1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}};
    // 传参:直接传入二维数组名(退化为数组指针)
    print2DArray(arr, 3); 
    return 0;
}

输出:

1 2 3 4 5 

6 7 8 9 10 

11 12 13 14 15 

注意:函数参数中 int (*p)[5] 等价于 int p[ ][5](两者都是数组指针的简写),但不能写成 int *p[5](这是指针数组,类型不匹配)。

到此这篇关于C语言中指针数组和数组指针的具体用法的文章就介绍到这了,更多相关C语言 指针数组和数组指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文