大家好啊,我是小象٩(๑òωó๑)۶
我的博客:Xiao Xiangζั͡ޓއއ
很高兴见到大家,希望能够和大家一起交流学习,共同进步。
今天我们复习前面学习的指针知识
目录
- 关于指针数组和数组指针的区别
-
- [指针数组(Array of Pointers)](#指针数组(Array of Pointers))
- [1 指针数组的定义](#1 指针数组的定义)
- 指针数组模拟二维数组
- [数组指针(Pointer to Array)](#数组指针(Pointer to Array))
- 字符指针变量,数组指针变量,函数指针变量的区别
- 结尾
关于指针数组和数组指针的区别
指针数组(Array of Pointers)
定义:一个数组,每个元素都是指针。
声明:int arr[size];
方括号[]优先级高,arr是数组,元素为int类型
C语言中的指针数组是一种特殊的数组,其元素都是指针类型。每个元素可以指向不同类型或相同类型的数据,常用于管理多个地址(如字符串数组、动态内存分配等)。
指针数组是指针还是数组?
我们类比一下,整型数组,是存放整型的数组,字符数组是存放字符的数组。
那指针数组呢?是存放指针的数组。
1 指针数组的定义
语法:数据类型 *数组名[数组长度];
特点:数组的每个元素都是一个指针,需单独初始化后才能使用。
示例:
c
int *ptr_arr[5]; // 定义一个包含5个整型指针的数组
char *str_arr[3]; // 定义一个包含3个字符指针的数组
指针数组的每个元素是地址,又可以指向一块区域。
指针数组模拟二维数组
c
#include <stdio.h>
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
int* parr[3] = { arr1, arr2, arr3 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
代码分析
数组定义:定义了三个一维整型数组 arr1、arr2 和 arr3,每个数组都包含 5 个整数元素。
指针数组定义与初始化:定义了一个指针数组 parr,它包含 3 个元素,每个元素都是 int* 类型的指针。将 arr1、arr2 和 arr3 的首地址分别赋值给 parr 的三个元素。
嵌套循环遍历:使用嵌套的 for 循环来遍历 parr 指针数组中的每个元素,并访问它们所指向的数组中的每个元素。外层循环控制访问哪个数组,内层循环控制访问数组中的每个元素。 输出结果:使用printf 函数将每个元素打印出来,并在每行结束时换行。
parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型一维数组,parr[i][j]就是整型一维数组中的元素。
上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。
数组指针(Pointer to Array)
定义:一个指针,指向整个数组。
声明:int (*ptr)[size];
括号()让ptr先被解释为指针,指向int[size]类型的数组。
数组指针变量是什么?
在C语言中,数组指针变量(也叫指向数组的指针)是一种特殊的指针变量,它指向的是一个数组。
之前我们学习了指针数组,指针数组是⼀种数组,数组中存放的是地址(指针)。
数组指针变量是指针变量?还是数组?
答案是:指针变量。
我们已经熟悉:
• 整形指针变量: int * pint; 存放的是整形变量的地址,能够指向整形数据的指针。
• 浮点型指针变量: float * pf; 存放浮点型变量的地址,能够指向浮点型数据的指针。
那数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。
形式:
c
int (*p)[5];
这里定义了一个名为p的指针变量,它指向一个包含5个int类型元素的数组。注意,(p)两边的括号不能省略,因为[]的优先级高于,如果没有括号int *p[5]; 这定义的是一个指针数组(一个包含5个int指针的数组),而不是指向数组的指针。
解释:p先和结合,说明p是⼀个指针变量,然后指针指向的是⼀个大小为5个整型的数组。所以p是
⼀个指针,指向⼀个数组,叫 数组指针。
这⾥要注意:[]的优先级要⾼于号的,所以必须加上()来保证p先和*结合。
数组指针变量怎么初始化
数组指针变量是用来存放数组地址的,那怎么获得数组的地址呢?就是我们之前学习的 &数组名 。
c
int arr[10] = {0};
&arr;//得到的就是数组的地址
如果要存放个数组的地址,就得存放在数组指针变量中,如下:
c
int(*p)[10] = &arr;
我们调试也能看到 &arr 和 p 的类型是完全⼀致的。
数组指针类型解析:
c
int (*p) [10] = &arr;
| | |
| | |
| | p指向数组的元素个数
| p是数组指针变量名
p指向的数组的元素类型
二维数组传参的本质
二维数组传参的本质是传递指向一维数组的指针,函数通过这个指针和已知的列数信息,按照连续内存存储的方式来访问和处理二维数组中的元素
有了数组指针的理解,我们就能够讲⼀下二维数组传参的本质了。
过去我们有⼀个二维数组的需要传参给⼀个函数的时候,我们是这样写的:
c
#include <stdio.h>
void test(int a[3][5], int r, int c)
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d ", a[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} };
test(arr, 3, 5);
return 0;
}
这⾥实参是⼆维数组,形参也写成⼆维数组的形式,那还有什么其他的写法吗?
⾸先我们再次理解⼀下⼆维数组,⼆维数组其实可以看做是每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏,是个⼀维数组。
所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是⼀维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 int [5] ,所以第⼀⾏的地址的类型就是数组指针类型 int(*)[5] 。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。如下:
c
#include <stdio.h>
void test(int (*p)[5], int r, int c)
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
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} };
test(arr, 3, 5);
return 0;
}
总结:⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式。
字符指针变量,数组指针变量,函数指针变量的区别
字符指针变量
本质上是一个指针,该指针专门用于指向字符类型的数据。在 C 语言里,由于字符串以字符数组形式存在且以空字符 '\0' 结尾,字符指针常被用于指向字符串常量或者字符数组。
例如:
c
#include <stdio.h>
int main() {
// 指向字符串常量
char *str = "Hello";
// 指向字符数组
char arr[] = "World";
char *ptr = arr;
return 0;
}
数组指针变量
同样是指针,但它指向的是一个数组。也就是说,此指针保存的是整个数组的起始地址,而非数组首元素的地址。
例如:
c
#include <stdio.h>
int main() {
int arr[3] = {1, 2, 3};
// 数组指针指向数组 arr
int (*p)[3] = &arr;
return 0;
}
函数指针变量
这是指向函数的指针。函数在程序编译后会被存储在内存中特定的代码段,函数指针存储的就是这个函数在内存中的起始地址,借助它可以调用该函数。
例如:
c
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
// 函数指针指向 add 函数
int (*funcPtr)(int, int) = add;
return 0;
}
使用场景
字符指针变量
常用于字符串处理,如字符串的复制、比较、查找等操作,也可用于动态分配内存存储字符串。
数组指针变量
主要用于处理多维数组,在函数参数传递时,能方便地操作二维或更高维数组。
函数指针变量
适用于实现回调函数、函数表等,可使程序在运行时动态选择要执行的函数,增强代码的灵活性和可扩展性。
结尾
这一课的内容就到这里了,下节课继续学习指针的其他一些知识
如果内容有什么问题的话欢迎指正,有什么问题也可以问我!