C语言day14-指针-二维数组

张开发
2026/4/9 15:11:42 15 分钟阅读

分享文章

C语言day14-指针-二维数组
一、数组与指针的基本概念1. 数组的三大特点连续性内存空间连续分配单一性元素类型相同有序性元素有固定顺序2. 二维数组的本质二维数组 一维数组的数组int a[3][4]; // 可以理解为有3个元素每个元素都是int[4]类型3. 核心类型辨析// 整型二维数组 int a[3][4]; int (*a)[4]; // ❌ 错误理解 // ✅ 正确a是数组名不需要* // 数组指针 vs 指针数组 char (*s)[4]; // 数组指针指向char[4]类型数组的指针 char* s[4]; // 指针数组有4个元素每个元素都是char*类型二、二维数组首元素的理解1. 首元素的双重含义int a[3][4]; 首元素a[0] // 1. 作为二维数组的首元素 // 2. 相当于是内部一维数组的数组名 // a. 类型 --- int[4]类型 // b. 值 --- 内部一维数组的首元素地址 a[0][0]2. 地址的层次关系a[0] // 1.行地址 a[0][0] // 内部一维数组的首元素 a[0][0] // 内部一维数组的首元素地址 a[0][0] // 地址值等价 a[0]关键理解a[0]的值等价于a[0][0]a[0]的类型是int[4]a[0]的类型是int[4]*C语言写作int(*)[4]三、数组指针的定义与使用1. 定义方式int a[3][4]; // 首元素是 a[0] // a[0] --- 行地址 // --- 确定地址类型 // --- a[0]的类型是 int[4] // --- a[0]的数据类型 --- int[4]* int (*p)[4] a[0]; // 正确定义 int (*p)[4] a; // 也正确a会退化为a[0]2. 指针运算详解int a[3][4]; int (*p)[4] a; 访问元素 p // 代表一行地址 pi // 第i行 行地址 *(pi) // 第i行 第0列首元素的地址 ---列地址 *(pi)j // 第i行 第j列 元素的地址 ---列地址 *(*(pi)j) // 第i行 第j列 元素表达式含义类型p代表一行地址int(*)[4]行指针pi第i行的行地址int(*)[4]行指针*(pi)第i行首元素地址降维int*列指针*(pi)j第i行第j列元素地址int*列指针*(*(pi)j)第i行第j列元素值int3. 等价表达式(1). a[i][j] (2). *(*(ai)j) (3). *(ai)[j] // a[i] *(ai) (4). *(a[i] j)四、字符型二维数组1. 基本使用char s[3][10] {hello, world, china}; char (*p)[10] s; // 访问方式 *(pi) // 第i行首字符地址 *(pi)j // 第i行第j列字符地址 (i0, j4)2. 内存布局char s[3][10] {hello, world, china}; 内存示意 p - |h|e|l|l|o|\0|...| (10字节) p1 - |w|o|r|l|d|\0|...| (10字节) p2 - |c|h|i|n|a|\0|...| (10字节)3. 关注点---字符串printf(%s\n, pi); // ❌ 不行 // pi是行地址 char(*)[10] // %s需要 char* 类型 printf(%s\n, *(pi)); // ✅ 正确 // *(pi)是列地址 char* // %s --- char* 整个字符串的首地址关键理解不行pi是行地址char(*)[10]正确*(pi)是首字符地址char*%s需要的是char*类型五、访问二维数组的两种方式方式1使用数组指针推荐int a[3][4]; int (*p)[4] a[0]; // 或 a int (*p)[4] a;方式2使用二维数组名直接访问int a[3][4]; // 直接用 a 访问a 等价于 a[0]六、指针数组一维指针数组1. 定义与特点char *s1 hello; char *s2 world; char *s3 china; char *s[3] {hello, world, china}; // s 是指针数组数组中存放的都是地址2. 二级指针操作char *s[3] {hello, world, china}; char **p s; // p指向指针数组的首元素 // 类型分析 s[0] // 首元素类型char* s[0] // 首元素地址类型char** // 使用 printf(%s\n, pi); // ❌ 错误pi是char** printf(%s\n, *(pi)); // ✅ 正确*(pi)是char*七、完整对比表1. 类型对比声明方式名称存储内容指针类型适用场景int a[3][4]二维数组12个intint(*)[4]固定大小的矩阵char s[3][10]字符二维数组3×10个字符char(*)[10]固定长度的字符串集合char *s[3]指针数组3个char*char**不同长度的字符串集合2. 内存布局对比// 二维数组 char s[3][10] {hello, world, china}; [h][e][l][l][o][\0][ ][ ][ ][ ] // 连续的30字节 [w][o][r][l][d][\0][ ][ ][ ][ ] [c][h][i][n][a][\0][ ][ ][ ][ ] // 指针数组 char *s[3] {hello, world, china}; s[0] - hello (在只读数据区) s[1] - world (在只读数据区) s[2] - china (在只读数据区) 数组本身只存储3个指针3. 操作对比操作二维数组指针数组定义指针char (*p)[10] s;char **p s;输出字符串printf(%s, *(pi));printf(%s, *(pi));修改字符✅ 可以s[0][0] H;❌ 不可以字符串常量改变指向❌ 数组名不可改变✅ 可以s[0] new;八、重点难点解析1. 降维操作的理解int (*p)[4]; // 行指针 p // 行指针int(*)[4] *(p) // 降维 - 列指针int* *(p)j // 仍是列指针 *(*(p)j) // 降维 - 元素值int记忆口诀每次*操作就是一次降维行指针 → 列指针 → 元素值2. 类型判断技巧// 看到 [] 在变量名右边 → 数组 char s[10]; // 数组 char *s[10]; // 指针数组数组优先级高 // 看到 () 包裹变量名 → 指针 char (*s)[10]; // 数组指针指针优先级被()提高 char (*s); // 普通指针3. 字符串输出的注意事项char s[3][10] {hello, world, china}; char (*p)[10] s; // ❌ 错误写法 printf(%s, p); // p是行指针不是字符指针 printf(%s, p1); // p1还是行指针 // ✅ 正确写法 printf(%s, *p); // *p是字符指针 char* printf(%s, *(p1)); // *(p1)是字符指针 char* printf(%s, p[1]); // p[1]等价于*(p1)九、课堂练习汇总练习1找出二维整型数组最大值int findMax(int (*p)[4], int row, int col);练习2字符串输入函数void inputStr(char (*p)[10], int row);练习3找出最大字符串int findMaxStr(char (*p)[10], int row);练习4字符串逆序void reverseStrings(char (*p)[10], int row);练习5字符串排序// 选择排序 void selectSort(char (*p)[10], int row); // 冒泡排序 void bubbleSort(char (*p)[10], int row);十、记忆要点总结1. 核心概念二维数组的首元素是一个一维数组a[0]数组名的值是地址类型是数组类型a[0]地址值等于a[0]但类型不同2. 指针类型数组指针int (*p)[4]← 指向数组指针数组int *p[4]← 数组存指针3. 访问元素// 二维数组 *(*(pi)j) p[i][j] a[i][j] // 记忆两次*降维两次[]索引4. 字符串操作二维数组printf(%s, *(pi));指针数组printf(%s, *(pi));关键确保传给%s的是char*类型5. 类型判断口诀优先级()[]*从变量名开始向右看[]是数组向左看*是指针遇到()就先处理括号内的终极理解指针的本质是类型系统不同的指针类型决定了指针运算时的步长1移动多少字节解引用时得到什么类型可以执行什么操作掌握了类型就掌握了指针1 #include stdio.h 2 int main(void) 3 { 4 int a[3][4] {1,2,3,4,5,6,7,8,9,10,11,12}; 5 int (*p)[4] a; 6 int i 0; 7 int j 0; 8 for(i 0;i 3;i) 9 { 10 for(j 0;j4;j) 11 { 12 printf(%d ,*(*(pi)j)); 13 } 14 putchar(\n); 15 16 } 17 return 0; 18 }

更多文章