程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<8>

大家好啊,我是小象٩(๑òωó๑)۶
我的博客:Xiao Xiangζั͡ޓއއ
很高兴见到大家,希望能够和大家一起交流学习,共同进步

今天我们复习前面学习的指针知识

目录

关于指针数组和数组指针的区别

指针数组(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;
}

使用场景

字符指针变量

常用于字符串处理,如字符串的复制、比较、查找等操作,也可用于动态分配内存存储字符串。

数组指针变量

主要用于处理多维数组,在函数参数传递时,能方便地操作二维或更高维数组。

函数指针变量

适用于实现回调函数、函数表等,可使程序在运行时动态选择要执行的函数,增强代码的灵活性和可扩展性。

结尾

这一课的内容就到这里了,下节课继续学习指针的其他一些知识
如果内容有什么问题的话欢迎指正,有什么问题也可以问我!

相关推荐
Orange--Lin15 分钟前
【ESP32指向鼠标】——icm20948与esp32通信
c语言·单片机·嵌入式硬件
不能只会打代码19 分钟前
Python人工智能技术全景:从基础框架到DeepSeek的突破性创新
开发语言·人工智能·python·deepseek
清风吹雨泡泡38 分钟前
HCIA-10.生成树 STP 3/3
开发语言·php
pink大呲花1 小时前
利用ES6 Set去重
开发语言·javascript·es6
蓝色洛特1 小时前
【matlab优化算法-17期】基于DBO算法的微电网多目标优化调度
开发语言·算法·matlab
siy23331 小时前
VS2022中cmath.h头文件功能介绍
c语言·笔记·学习
天天进步20151 小时前
Java全栈项目实战:在线课程评价系统开发
java·开发语言
ONE_PUNCH_Ge2 小时前
Python 量化
开发语言·python
Mr-Wanter2 小时前
使用 JFreeChart 创建动态图表:从入门到实战
开发语言·python·信息可视化
Strive_Sun2 小时前
Windows 下搭建 googletest 测试框架(C/C++)
c语言·开发语言·c++·windows