重庆方言网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1171|回复: 0
打印 上一主题 下一主题

二重指针详解

[复制链接]
跳转到指定楼层
楼主
发表于 2020-3-13 17:42:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    (1)二重指针本质上也是指针变量,和普通指针的差别就是它指向的变量类型必(2)C语言中如果没有二重指针行不行?其实是可以的。一重指针完全可以做二一维数组在内存中是连续分布的多个内存单元组成的,而二维数组在内存中也是连既然二维数组都可以用一维数组来表示,那二维数组存在的意义和价值在哪里?明接着看a[0],此时的a[0]有两重身份:在二维数组的第一个维度里a[0通过“数组名代表数组首元素的地址”可知,a[0]等价于&a[0][0]。还是拿数组a[2][5]举例,在第一维度里,该数组有两个元素,分别是a[当a即是二维数组名称,但是同时a也表示二维数组的第一个小一维数组(a[0如二维数组inta[2][5],能指向改二维数组的数组指针类型为int(很多人对p要进行两次解引用才能得到值,表示不理解,如果读者能想到前面提到




二重指针詳解
朱有鹏
1.二重指针
1.1、二重指针与普通一重指针的区别
本质上来说,二重指針和一重指针的本质都是指針变量,指针变量的本质就是变量。
一重指针變量和二重指针變量本身都占4字节内存空間,
1.2、二重指針的本质
(1)二重指針本质上也是指针變量,和普通指针的差别就是它指向的变量类型必须是个一重指針。二重指針其实也是一種数据類型,编译器在编译时会根据二重指针的数据类型来做静态類型檢查,一旦发现運算时数据类型不匹配編譯器就会報错。
(2)C语言中如果没有二重指针行不行?其实是可以的。一重指针完全可以做二重指针做的事情,之所以要发明二重指針(函数指針、数组指针),就是為了让编译器了解这個指针被定义时定义它的程序员希望這个指針被用来指向什么東西(定义指针時用数据类型來標记,譬如int *p,就表示p要指向int型数据),编譯器知道指针類型之后可以帮我們做静态类型检查。编譯器的这种靜態类型检查可以辅助程序员发现一些隐含性的编程错误,这是C语言给程序员提供的一種編译時的查錯机制。
(3)为什么C语言需要發明二重指针?原因和发明函数指针、数组指针、结构体指针等一樣的。
1.3、二重指针的用法
(1)二重指針指向一重指針的地址
(2)二重指针指向指针数組的
(3)实践编程中二重指针用的比较少,大部分时候就是和指针数组結合起来用的。
(4)实践编程中有时在函数传参時为了通过函数内部改变外部的一个指针變量,会传這个指针变量的地址(也就是二重指针)进去


1.4、二重指针与数组指针
(1)二重指针、数组指针、結构体指针、一重指针、普通变量的本质都是相同的,都是变量。
(2)所有的指针变量本質都是相同的,都是4个字節,都是用來指向别的东西的,不同類型的指针变量只是可以指向的(编译器允許你指向的)变量类型不同。
(3)二重指针就是:指针數组指针


2、二维数组

2.1、二维數组的内存映像
一维数组在内存中是连續分布的多个内存单元组成的,而二维數组在内存中也是连续分布的多個內存单元组成的。從内存角度来看,一维數組和二维数組没有本質差别。如:二维数组int a[2][5]和一維数组int b[10]对应關系如下:
a[0][0]    a[0][1]    a[0][4]    a[1][0]    a[1][1]    a[1][4]
b[0]       b[1]       b[4]       b[5]       b[6]       b[9]
既然二维数组都可以用一维数组來表示,那二维数组存在的意义和价值在哪里?明确告诉大家:二维數组a和一维数组b在内存使用效率、访問效率上是几乎相同。使用用二維数组而不用一维数组,原因是在某些情况下,二維数组更好理解、利于組織。我们使用二維数组,并不是必须,而是一种简化编程的方式。一维数组的出現其实也不是必然的,也是為了简化編程。
2.2、二维数组的識别之第一維和第二维
二維数组必然是兩个维度,假設数组为a[2][5]从左到右看:
[2]是第一个维度,表示a这个數组里有两个元素。
[5]是第二个维度,需要进入第一维度的內部观察。它的内部有5個int型的元素。

数组为a[2][5]內部模型

對后面小节的理解,请读者结合上图进行理解。


2.3、数组名代表数組首元素的地址
“数组名代表数组首元素的地址”这句话既适用于一维数组,也适用于二维数組。
对于一維數组int a[5]而言:数組名a就表示首元素a[0]的地址,及數组名a等价于&a[0]。
對于二維数a[2][5]组而言:数组名a就表示首元素a[0]的地址,及数組名a等价于&a[0]。
接着看a[0],此时的a[0]有两重身份:在二维数组的第一个维度里a[0]是数組的首元素;而在第二维度里,a[0]本身就是个数组,该數組的首元素是a[0][0],所以此时a[0]也代表一个数組名。(本段结论同样适合a[1])。
通过“数组名代表数组首元素的地址”可知,a[0]等价于&a[0][0]。而前面同时有a等价于&a[0]的结论,所以可以得到a等價于&&a[0][0]。記住这个结論,对后面理解数组指針访问二維数组的方式大有助益。
2.4、指针访問二维数组的兩种方式
2.4.1、普通指针指向二维數組的第一維
还是拿数组a[2][5]举例,在第一维度里,该数组有两个元素,分别是a[0]和a[1],而a[0]和a[1]本身是個一維数组,及a[0]和a[1]就是数组的数组名,所以我们可以像访问普通的一維数组那样访問a[0]和a[1]:
int* p1 = a[0];//數组名代表数组首元素的地址
int* p2 = a[1];//数组名代表数组首元素的地址
printf("a[0][0] = %d.\n", *p1);

//*p1对应的是a[0][0]的值
printf("a[0][1] = %d.\n", *(p1+1));
//*(p1+1)对应的是a[0][1]的值
printf("a[1][0] = %d.\n", *p2);

//*p2对應的是a[1][0]的值
printf("a[1][1] = %d.\n", *(p2+1));
//*(p2+1)对應的是a[1][1]的值
2.4.2、數组指针访問二维數组

终于到了本章节的重点,前面的内容都是这节的鋪垫。
比如:int a[3][3]这样一個二位數組来说,通过前面的學习,我们已经知道,a[3][3]可以分為如下三个小一维数组,
a[0][0] a[0][1] a[0][2]
a[1][0] a[1][1] a[1][2]
a[2][0] a[2][1] a[2][2]
当a即是二維数组名称,但是同时a也表示二维数组的第一个小一维数組(a[0][0] a[0][1] a[0][2])的整個数组的數组首地址,a等价于a[0],那么一问就来了,什么样的指針才能存放数组首地址呢?答案就是数组指針。






如二維数组int a[2][5],能指向改二维數組的数組指针類型为int (*)[5],需要注意的是數组指针類型中的5不是乱填的,它的值必须和他指向的二维数组的第二维中的元素相等。如 char b[77][9]那么此时需要的數组指针類型为char (*)[9]。
了解數組指针的选型之后,就来讲解数組指针访問二維数组的过程,还以int a[2][5]為例:
int (*p)[5] = a;//數組指针p指向二维数組a[2][5]
那么如何通过p来访问a[2][5]中的元素呢:
printf("a[0][0] = %d.\n",**p);

//**p对应的是a[0][0]的值
printf("a[0][1] = %d.\n",*(*p+1));
//*(*p+1)对应的是a[0][1]的值
printf("a[0][4] = %d.\n",*(*p+4));
//*(*p+1)对應的是a[0][4]的值


printf("a[1][0] = %d.\n",**(p+1));
//**(p+1)對應的是a[1][0]的值
printf("a[1][1] = %d.\n",*(*(p+1)+1));//*(*(p+1)+1)对应的是a[1][1]的值
printf("a[1][4] = %d.\n",*(*(p+1)+4));//*(*(p+1)+4)对应的是a[1][4]的值


很多人对p要进行两次解引用才能得到值,表示不理解,如果读者能想到前面提到的结论,可能會恍然大悟。前面結论提到——當a是二维数组的数組名时,a等价于&&a[0][0]。首先,a和數组指针p是类型匹配的;其次“解引用(*)”和“取地址(&)”这個兩个过程是逆过程。之前a[0][0]连续取两次地址才和a等价,那现在p连续兩次解引用得到a[0][0]也是理所当然(**p對应的是a[0][0]的值)。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Baidu

手机版|小黑屋|联系我们|重庆方言网

GMT+8, 2024-5-1 15:39 , Processed in 0.156250 second(s), 17 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表