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语言 指针数组和数组指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


最新评论