简单不先于复杂,而是在复杂之后。
目录
1. 字符指针
面试题
2. 指针数组
3. 数组指针
3.1 数组指针的定义
3.2 &数组名 VS 数组名
3.3 数组指针的使用
4. 数组参数、指针参数
4.1 一维数组传参
4.2 二维数组传参
4.3 一级指针传参
4.4 二级指针传参
1. 字符指针
指针的概念:
1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)
3. 指针是有类型的,指针的类型决定了指针+-整数的步长,指针解引用的权限。
4. 指针运算
在指针的类型中有一种类型叫字符指针char*
所以在我们敲代码的时候,把常量字符串首字符地址赋给指针变量的时候,最好前面加上const,保护字符串不被更改
面试题
2. 指针数组
首先,我们定义了3个整型数组,arr1、arr2、arr3,并使用指针数组存储了这三个数组首元素的地址,然后用两层循环打印出这三个数组的所有元素。
外层循环控制数组的遍历,内层循环控制数组中每个元素的访问。
在内层循环中,通过 parr[i][j] 访问第 i 个数组的第 j 个元素,然后用 printf 输出元素的值。
注释部分的 *(p+i) == p[i]
这句注释解释了指针数组 parr 的用法。
parr 是一个指针数组,定义为 int* parr[3] ,int表示数组中存储的是指向 int 类型的指针。
由于指针数组的本质就是一个数组,所以可以使用 *(p+i) == p[i] 的方式访问数组 parr中的元素,它们的含义是相同的,都表示取出第 i 个元素(第 i 个数组首元素的地址)。
注释部分的printf("%d ", *parr[i] + j);
这行代码的含义是用指针方式访问数组元素。
*parr[i] 表示取出第 i 个数组的首元素的值,然后将其加上 j ,表示访问第 i 个数组的第 j 个元素的值。
这种方式和 parr[i][j]是等价的,但是后者比较直观。
int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,5,6 }; int* parr[3] = { arr1,arr2,arr3 }; //0 1 2 int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 5; j++) { //*(p+i) == p[i] //printf("%d ", * parr[i] + j); printf("%d ", parr[i][j]); } printf("\n"); } return 0; }
3. 数组指针
3.1 数组指针的定义
int (*p)[10];
解释:
p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组。
所以p是一个指针,指向一个数组,叫做数组指针。
注:[ ]的优先级高于* ,必须加上()来保证p先和*结合。
3.2 &数组名 VS 数组名
数组名表示的通常都是数组首元素的地址,但是有两个意外:
1. sizeof(数组名) ,这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名 ,这里的数组名表示的依然是整个数组。所以&的数组名取出的是整个数组的地址。
数组指针在定义的时候,C语言的规范要求必须指定数组的数据类型和元素个数。
数组指针中的[ ]的值必须与它指向数组的元素个数相等。
在vs跑代码的时候我发现,vs2019对这方面检测不严格,可以跑,但是在事实上却有很大的隐患,所以在我们敲代码的时候要注意代码规范。
如果[ ]中的值与实际数组元素个数不同,可能会导致访问越界或内存泄露等问题。
如果[ ]中不写值,有时编译器会报错,因为它无法确定指针指向的数组的大小。
这是错误别扭的写法,最好不要这样用。
这是简洁清晰的写法。
3.3 数组指针的使用
既然数组指针指向的是数组,那数组指针存放的应该是数组的地址。
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void print1(int arr[3][5], int r, int c) { int i = 0; for (i = 0; i < r; i++) { int j = 0; for (j = 0; j < c; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void print2(int(*p)[5], int r, int c) { int i = 0; for (i = 0; i < r; i++) { int j = 0; for (j = 0; j < c; j++) { printf("%d ", *(*(p + i) + j)); } printf("\n"); } } int main() { int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; print1(arr, 3, 5); print2(arr, 3, 5); return 0; }
这两种写法都是可以的。
4. 数组参数、指针参数
在写代码的时候要把【数组】和 【指针】传给函数,接下来我们学习函数的参数如何设计。
4.1 一维数组传参
4.2 二维数组传参
4.3 一级指针传参
4.4 二级指针传参