☰
C语言指针与数组深度解析2(详细易理解)
2026/10/4 11:57:59 网站建设 项目流程

🏆浮世尘弦:个人主页

⭐个人专栏:《C语言》、《数据结构与算法》、《C++》

💎:非淡薄无以明志,非宁静无以致远


文章目录

一,深入理解数组名

二,使用指针访问数组

三,一维数组传参的本质

四,冒泡排序

五,二级指针

六,指针数组

七,字符指针变量

八,数组指针变量

1,定义

2,表示

3,数组指针的初始化

九,二维数组传参的本质

1,剖析二维数组

2,运用展示:

十,函数指针变量

十一,关键字typedef

1,typedef的定义和运用

2,typedef和define的区别

十二,函数指针数组

1,定义

2,运用:

十三,转移表


一,深入理解数组名

1,引出问题

通过上述代码可知arr确实是首元素的地址,但是在sizeof中的arr又表示出了40个字节,这就又表示arr代表的是整个数组,产生了矛盾。

结论:说数组名就是地址是正确的。不过有两个例外:

1.sizeof(arr):此时arr表示的是整个数组的大小

2,&arr,此时代表的是arr整个数组的地址

通过下面的分析:

由上图可知:

arr和&arr[0]都代表着数组首元素的地址,所以他们加1时,地址改变一个整型变量的大小, 但是&arr表示的是整个数组的地址,所以在加1时,直接跳过了40个字节(一个整型占4个字节)。

只是由于&会选取最小的一个进行表示,故&arr可以表示首元素的地址。

二,使用指针访问数组

由arr[i] = *(arr+i)

得:*(i+arr)=i[arr] 注意:i[arr]也可以但是不建议使用,因为会影响代码的可读性。

总结:

1,数组就是数组,是一块连续的空间(大小取决于数组内元素的个数和元素的类型)

2,指针(变量)就是指针(变量),是一个变量(大小为4/8个字节)

3,数组名是地址,是首元素的地址。

4,可以使用指针来访问数组。

三,一维数组传参的本质

总结:1,数组传参时传入的是首元素的地址,产生了传址调用,因此形参和实参是同一个数组,不会创建新的地址。

2,形参的数组是不会再创建地址空间的,所以形参的数组是可以忽略掉数组的大小,写成arr[ ]

3,一维数组传参时,形参可以写成数组形式,也可以写成指针形式。

四,冒泡排序

冒泡排序的核心思想是:对相邻两个元素进行比较,然后进行排序。

分析:对一个数组内的元素进行排序

例如数组内元素为: 10 9 8 7 6 5 4 3 2 1

按照升序的方式排列:1 2 3 4 5 6 7 8 9 10

我们需要先选取10和9两个元素进行比较,在交换两个元素的位置,依次往下进行,当遍历完数组内所有元素后变为9 8 7 6 5 4 3 2 1 10。接着我们需要重复上述过程,总共进行遍历9次,得到升序数组。

代码实现:

五,二级指针

二级指针就是指针变量的地址

结果为:0 //**pp两次解引用为a, *pp一次解引用为p

int*表示pp指向对象的类型,*表示pp为一个指针变量

p+1跳过4个字节(取决于p的类型)pp+1跳过4或8个字节(取决于是x64还是x86)在确定环境下,指针的大小是不变的。

六,指针数组

指针数组的本质是数组,数组内的元素为指针变量。

运用:

七,字符指针变量

两种字符指针:

1,接收数组内容,可变。

2,接收常量字符串内容,不可变。

打印结果:

wbcdef

wbcdef

abcdef

补充:char* ps = "abcdef"可更改为const char* ps = "abcdef",这样出现*ps更改时可以直接拦截,并在编译器中报错。

例题:

输出结果:

not same

same

分析:

srt1和str2是创建的两个不同的数组,虽然内容一样,但是首元素的地址不一样,同时两个都可以进行更改,故不相同。

首先arr1和arr2表示的是首元素的地址,arr1和arr2指向的是同一个字符串常量,这个常量字符串被储存在一个地址中,不可更改。故相同。

八,数组指针变量

1,定义

类比:

整形指针变量:int* print:指针存放的地址是整型变量的地址,能够指向数据。

数组指针变量:本质上是一种指针,存放的是数组的地址(不是数组首元素的地址),能够指向数组。

2,表示

int* p1[10] //指针数组,本质上是数组,数组内存放的是地址

int (*p2)[10] //数组指针,本质上是指针

理解:由于()的优先级比[]高,使得*和p2进行结合。故*p2可以表示指针,去掉(*p2)剩下的部分:int表示指针指向的是一个整形数组类型,[10]数组内储存的元素的个数为10

3,数组指针的初始化

int (*p2) [10] = &arr; //&arr可以表示整个数组的地址。

九,二维数组传参的本质

1,剖析二维数组

二维数组可以看成每个元素都是一个一维数组的数组。

换一种解读:arr[3][5]前面的arr[i]表示的是数组的每一行,后面的[5]表示的是每一行(一维数组)中的各个元素。

可以把每一行当作数组中的每一个元素,我们知道数组在传参时传入的是首元素的地址,又因为二维数组的首元素是一个数组,所以要接收它就要用到数组指针变量int (*p)[10]。

2,运用展示:

分析:形参可以传二维数组arr[3][5],也可以传数组指针int(*p1)[5],本质上都是数组首元素的地址,即第一行的地址。

十,函数指针变量

1,函数的地址

函数是有地址的,函数名就是函数的地址,其次&函数名这种形式也可以表示函数的地址。

如果想要将函数的地址存储起来,并运用的话,就要创建一个指针来接收它,这个指针就是函数指针变量。

类比数组指针引出函数指针:

数组指针:int (*p1)[10]

函数指针 :int (*p2)(int x,int y) =&add

分析:p2中存放的是函数的地址 ,int表示函数的返回类型,(int x,int y)表示函数的参数,可省略为(int,int).&add表示函数的地址,可省略为add.

2,运用

分析:ps和(*ps)都可以表示地址

分析复杂调用:

1,

2,

十一,关键字typedef

1,typedef的定义和运用

typedef的作用是用来重命名的,可以将复杂的类型进行简化。

展示:

2,typedef和define的区别

typedef int* nrt

#define NRT_T int*

nrt p1,p2

p1和p2都是指针变量

NRT_T p3,p4

p3是指针变量,p4是整型变量

原因:替换后 int*p3 p4 故只有p3是指针变量

十二,函数指针数组

1,定义

把一个函数的地址放到数组中,这个数组就叫做函数指针数组。

语法:

int (*parr[4])(int,int) = {add,,sub,mul,div};

parr[4]表示数组,parr是数组名,[4]是数组的个数。

int(*)(int,int)表示是函数指针类型。

{}内的是同类型的不同的函数名。

2,运用:

十三,转移表

模拟实现计算机

主调函数

分析:

让arr[5]数组的首元素为0,第一可以使得arr[input]中的input和数组进行正确匹配。

二是可以补充输入0的情况。

中间调用函数

回调函数

回调函数就是通过函数指针调用的函数。

把一个函数的指针作为参数传递给另一个函数,另一个函数在使用这个指针时所调用的函数就是回调函数。

主调函数把函数的指针传给中间调用函数,中间调用函数利用函数指针找到回调函数,对回调函数进行操作再返回内容到主调函数中。

转移表通过函数指针的方式,实现了对不同函数相似操作,降低了函数一个一个进行相似操作而带来的代码冗余,节省了空间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询