C语言指针与数组笔记
1. 指针数组 (Array of Pointers)
- 本质:数组,每个元素都是指针
- 声明语法:
类型 *数组名[大小]
声明示例
int *ptr_arr[5]; // 5个整型指针的数组
char *str_arr[3]; // 3个字符指针的数组
float *float_arr[10]; // 10个浮点指针的数组
使用示例
#include <stdio.h>
int main() {
int a = 10, b = 20, c = 30;
int *ptr_arr[3] = {&a, &b, &c};
// 读取方式
for(int i = 0; i < 3; i++) {
printf("ptr_arr[%d] = %p\n", i, ptr_arr[i]); // 指针值(地址)
printf("*ptr_arr[%d] = %d\n", i, *ptr_arr[i]); // 解引用
printf("*(ptr_arr + %d) = %d\n", i, *(ptr_arr[i])); // 等价写法
}
return 0;
}
字符串指针数组(常用)
char *fruits[] = {"Apple", "Banana", "Orange"};
for(int i = 0; i < 3; i++) {
printf("fruits[%d] = %s\n", i, fruits[i]);
}
2. 数组指针 (Pointer to Array)
- 本质:指针,指向整个数组
- 声明语法:
类型 (*指针名)[大小]
声明示例
int (*arr_ptr)[5]; // 指向包含5个整数的数组
char (*char_ptr)[10]; // 指向包含10个字符的数组
使用示例
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int (*arr_ptr)[5] = &arr; // 取整个数组的地址
// 三种等价的读取方式
for(int i = 0; i < 5; i++) {
printf("(*arr_ptr)[%d] = %d\n", i, (*arr_ptr)[i]); // 推荐
printf("arr_ptr[0][%d] = %d\n", i, arr_ptr[0][i]);
printf("*(*arr_ptr + %d) = %d\n", i, *(*arr_ptr + i));
}
return 0;
}
3. 多维数组指针
指向整个二维数组
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 指向整个3x4二维数组
int (*mat_ptr1)[3][4] = &matrix;
// 读取方式
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 4; j++) {
printf("(*mat_ptr1)[%d][%d] = %d\n", i, j, (*mat_ptr1)[i][j]);
}
}
指向行(更常用)
// 指向包含4个整数的行
int (*row_ptr)[4] = matrix; // 等价于 &matrix[0]
// 读取方式
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 4; j++) {
printf("row_ptr[%d][%d] = %d\n", i, j, row_ptr[i][j]);
}
}
函数参数中的多维数组指针
// 接收二维数组指针作为参数
void print_matrix(int (*arr)[4], int rows) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < 4; j++) {
printf("%2d ", arr[i][j]);
}
printf("\n");
}
}
// 调用
print_matrix(matrix, 3);
4. 关键区别总结
| 类型 | 声明 | 含义 | 内存布局 |
|---|---|---|---|
| 指针数组 | int *arr[5] |
5个int指针的数组 | [ptr1, ptr2, ptr3, ptr4, ptr5] |
| 数组指针 | int (*arr)[5] |
指向5个int数组的指针 | ptr → [int, int, int, int, int] |
| 二维数组指针 | int (*arr)[4] |
指向4个int数组的指针 | ptr → [int×4], 可递增到下一行 |
5. 记忆技巧
运算符优先级规则
int *arr[5]; // []优先级高:指针的数组
int (*arr)[5]; // ()改变优先级:数组的指针
阅读技巧:从内向外,从右向左
int *ptr[5]; // ptr是数组[5],元素是int指针
int (*ptr)[5]; // ptr是指针,指向int数组[5]
6. 综合示例
#include <stdio.h>
int main() {
// 1. 指针数组
int a=1, b=2, c=3;
int *ptr_arr[] = {&a, &b, &c};
// 2. 数组指针
int arr[3] = {10, 20, 30};
int (*arr_ptr)[3] = &arr;
// 3. 二维数组指针
int matrix[2][3] = {{1,2,3}, {4,5,6}};
int (*mat_ptr)[3] = matrix;
printf("指针数组:\n");
for(int i=0; i<3; i++)
printf("%d ", *ptr_arr[i]);
printf("\n数组指针:\n");
for(int i=0; i<3; i++)
printf("%d ", (*arr_ptr)[i]);
printf("\n二维数组指针:\n");
for(int i=0; i<2; i++) {
for(int j=0; j<3; j++) {
printf("%d ", mat_ptr[i][j]);
}
}
return 0;
}
核心要点:理解声明中的优先级,明确操作的是指针还是数组。