二重指针详解

合集下载

二级指针的用法

二级指针的用法

二级指针的用法
二级指针是指指向指针的指针。

它在C语言中经常用于动态内存分配、多级数据结构中的数据类型以及函数指针的使用。

二级指针的使用可
以让程序在操作指针的过程中更加灵活,提高程序的可读性和可维护性。

动态内存分配是二级指针的重要应用之一。

在程序运行过程中,可以
使用malloc()函数来动态分配内存空间。

此时需要声明一个指向一级
指针的二级指针,通过将一级指针指向所分配的内存空间,即可实现
动态内存分配。

另一个常见应用是在多级数据结构中使用二级指针。

例如,要在一个
链表中插入一个新节点,需要将这个节点链接到链表中的某个位置。

此时需要将这个节点的地址存储在一个指向节点指针的指针中,即二
级指针。

这样可以在链表中动态添加或删除节点,提高程序的效率和
灵活性。

函数指针也可以使用二级指针。

为了扩展函数指针的功能,可以使用
二级指针作为函数的参数或返回值。

例如,可以使用一个指向指针的
指针来修改原指针所指向的数据,或者在函数中创建一个新指针并返
回其地址。

总之,二级指针在C语言中扮演着重要的角色。

使用二级指针可以提高程序的灵活性和可维护性。

需要注意的是,在使用二级指针时,需要特别小心,避免产生内存泄漏等问题。

因此,在编写程序时,需要仔细考虑数据结构的设计,确保使用二级指针的正确性和安全性。

双指针 算法原理

双指针 算法原理

双指针算法是一种高效的编程技巧,在处理线性数据结构如数组和链表时尤为有用。

它通过同时维护两个或多个指针在数据结构上的位置,并根据特定条件调整这些指针的位置关系,来解决一系列复杂度较高的问题。

双指针方法通常可以将时间复杂度从O(n^2)降低到O(n),从而极大地提高了代码执行效率。

双指针算法的基本形式:1.同步指针:o两个同向移动的指针:在这种模式下,两个指针按照相同的方向遍历数据结构,例如在数组中,两个指针从头或尾部开始,逐步向中间靠拢。

这种策略常用于查找数组中的有效对(如数组中和为给定值的元素对)、去除重复元素等问题。

2.快慢指针:o两个不同步速的指针:其中一个指针(快指针)比另一个指针(慢指针)移动更快,通常是每次移动两个单位而非一个单位。

此策略适用于判断链表是否有环、找到环的入口点、找出链表的中点等场景。

3.对撞指针:o两个反向移动的指针:两个指针从两端开始向中间移动,直到相遇为止。

这种技术常用于去除重复字符形成唯一字符串、寻找旋转数组中的最小/最大元素、找出无重复子数组的最大长度等问题。

算法原理与应用实例:•删除排序数组中的重复项:在已排序的数组中,我们可以设置两个指针i和j,初始时都指向数组的第一个元素。

i指针用来遍历数组,j指针则指向最后一个未重复的元素之后的位置。

当i所指向的元素与j-1所指向的元素不同时,才将arr[i]的值复制到arr[j],并将j向前推进一位。

这样,j之前的区域就是去重后的数组部分。

•寻找两个有序数组的中位数:在一个问题中,有两个升序排列的数组,我们可以通过分别从两个数组头部开始移动两个指针,使得它们所指向的元素之和尽可能接近整个合并后数组的中位数,进而快速求解中位数。

•检查回文串:在字符串中确定是否为回文,可以通过使用一对指针分别从首尾开始向中间移动,比较对应位置上的字符是否相同,若所有对应字符都相同,则字符串为回文。

总之,双指针算法的核心在于利用指针之间的相对位置关系来巧妙地解决问题,其关键在于理解问题的本质并合理设计指针的移动规则,以达到解决问题的目的。

c语言二级指针详解

c语言二级指针详解

c语言二级指针详解C语言中,指针是一种重要的数据类型,它可以指向另一个变量或者数据结构中的一个元素,并且可以进行不同种类的操作(如解引用、赋值、比较、运算等)。

在C语言中,指针本身也是一个变量,它具有一个内存地址,并且其值就是指向的地址。

而指针变量可以通过指定自己的类型来控制指向的变量或者数据结构元素的类型。

在C语言中,指针本身也可以被指针所指向,这样的指针就被称为“二级指针”或者“指向指针的指针”。

二级指针在一些情况下比普通指针更加灵活,比如当我们需要在函数内部进行指针变量的修改或者返回值时,就可以使用二级指针。

1、指向指针的指针需要使用两个星号(**)来声明,例如:int **p;2、在函数中传递指向指针的指针时,需要将变量的地址传递给函数,而函数需要使用指向指针的指针来访问实际的指针变量。

3、在使用二级指针时,我们需要防止指针变量指向非法内存地址,否则会导致程序出现意想不到的错误。

二级指针是C语言中非常重要的概念,尤其在函数调用和指针变量的修改或返回值时,更是非常有用。

不过,我们在使用二级指针时需要额外注意指向内存地址的合法性,否则会导致程序出现异常。

二级指针是指指向指针对象的指针,即指针的指针,它可以通过间接的方式访问一个指针变量所指向的地址,这种间接的访问方式可以增加程序的灵活性,从而使程序更加易于理解和维护。

1、动态内存管理在C语言中,动态内存分配是通过调用malloc函数来实现的,而释放动态内存则需要使用free函数。

在使用malloc函数分配内存时,它会返回一个指针,指向分配的内存空间的首地址,我们可以将这个指针赋值给一个普通的指针变量,然后通过这个普通指针变量来访问分配的内存空间。

不过,当我们使用malloc来分配一个指针数组时,我们就需要使用二级指针来存储这个指针数组的首地址。

int **p = (int **)malloc(sizeof(int *) * 10);for (int i = 0; i < 10; ++i) {p[i] = (int *)malloc(sizeof(int) * 10);}以上代码中,我们使用了二级指针来存储指向指针数组的地址,然后使用循环语句来为每一个指针分配空间。

二级指针的函数参数传递问题

二级指针的函数参数传递问题
void main()
{
char *p=NULL;
myMalloc(p); //这里的p实际还是NULL,p的值没有改变,为什么?
if(p) free(p);
}
void myMalloc(char *s) //我想在函数中分配内存,再返回
{
s=(char *) malloc(100);
}
myMalloc(p)的执行过程:
什么是值参(实参)和形参?
函数的参数分为形参和实参两种。形参出现在函数定义中,在整个函数体内都可以使用,实参出现在主调函数中,形参和实参的功能是作数据传送。
发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送
值参:只传递数值,在过程(函数)中对之所进行的改动,不会造成原始变量值的改变.与之相对的是地址参数,传的是变量地址,所以在函数中的任何改动都会影响到主函数的实际参数
}
void main()
{
char *p=NULL;
myMalloc(p); //这里的p实际还是NULL,p的值没有改变,为什么?
if(p) free(p);
}
程序2:void myMalloc(char **s)
{
*s=(char *) malloc(100);//S指向的是P的地址,所以改变了P所指的内存单元.
void fun(int *p)
{
int b=100;
p=&b;
}
main()
{
int a=10;
int *q;
q=&a;
printf("%d\n",*q);
fun(q);
printf("%d\n",*q);

双重指针的用法

双重指针的用法

双重指针的用法双重指针是指一个指针变量的地址存储在另一个指针变量中,也就是指向指针的指针。

它的主要作用是可以通过改变指针变量的值,来改变指针所指向的变量。

双重指针通常用于以下几种情况:1. 函数参数传递:当需要在函数中修改指针指向的变量时,可以使用双重指针作为函数的参数。

这样可以将指针变量的地址传递给函数,通过修改指针变量的值来改变原始指针的指向。

```c++void modifyPointer(int** p) {int* newPtr = new int(10);*p = newPtr; // 改变原始指针的指向}int main() {int* ptr = nullptr;modifyPointer(&ptr);// 现在ptr指向了一个新的内存地址return 0;}```2. 动态内存分配:当需要动态分配多级指针所指向的内存时,可以使用双重指针。

一级指针用于指向二级指针,二级指针再指向实际的内存。

```c++int** allocate2DArray(int row, int col) {int** arr = new int* [row];for (int i = 0; i < row; i++) {arr[i] = new int[col];}return arr;}int main() {int** arr = allocate2DArray(3, 4);// arr现在指向一个二维数组return 0;}```3. 字符串处理:在处理字符串时,双重指针可以用于修改或返回指向字符串的指针。

```c++void modifyString(char** str) {char* newStr = new char[20];strcpy(newStr, "Hello, World!");*str = newStr;}int main() {char* str = nullptr;modifyString(&str);// 现在str指向了一个新的字符串return 0;}```需要注意的是,在使用双重指针时需要确保所指向的内存已经被分配,避免出现悬空指针或内存泄漏的情况。

C语言指针用法详解

C语言指针用法详解

C语言指针用法详解C语言指针用法详解指针可以说是集C语言精华之所在,一个C语言达人怎么可以不会指针呢。

下面店铺给大家介绍C语言指针用法,欢迎阅读!C语言指针用法详解(1)关于指针与数组的存储a、指针和数组在内存中的存储形式数组p[N]创建时,对应着内存中一个数组空间的分配,其地址和容量在数组生命周期内一般不可改变。

数组名p本身是一个常量,即分配数组空间的地址值,这个值在编译时会替换成一个常数,在运行时没有任何内存空间来存储这个值,它和数组长度一起存在于代码中(应该是符号表中),在链接时已经制定好了;而指针*p创建时,对应内存中这个指针变量的空间分配,至于这个空间内填什么值即这个指针变量的值是多少,要看它在程序中被如何初始化,这也决定了指针指向哪一块内存地址。

b、指针和数组的赋值与初始化根据上文,一般情况下,数组的地址不能修改,内容可以修改;而指针的内容可以修改,指针指向的内容也可以修改,但这之前要为指针初始化。

如:int p[5];p=p+1; 是不允许的而p[0]=1; 是可以的;//int *p;p=p+1; 是允许的p[0]=1; 是不允许的,因为指针没有初始化;//int i;int *p=&i;p[0]=1; 是允许的;对于字符指针还有比较特殊的情况。

如:char * p="abc";p[0]='d'; 是不允许的为什么初始化了的字符指针不能改变其指向的内容呢?这是因为p 指向的是“常量”字符串,字符串"abc"实际是存储在程序的静态存储区的,因此内容不能改变。

这里常量字符串的地址确定在先,将指针指向其在后。

而char p[]="abc";p[0]='d'; 是允许的这是因为,这个初始化实际上是把常量直接赋值给数组,即写到为数组分配的内存空间。

这里数组内存分配在先,赋值在后。

(2)关于一些表达式的含义char *p, **p, ***p;char p[],p[][],p[][][];char *p[],*p[][],**p[],**p[][],*(*p)[],(**p)[],(**p)[][];能清晰地知道以上表达式的含义吗?(知道的去死!)第一组:char *p, **p, ***p;分别为char指针;char*指针,即指向char*类型数据地址的指针;char**指针,即指向char**类型数据的指针;他们都是占4字节空间的指针。

《C语言》指针--ppt课件全文

《C语言》指针--ppt课件全文

说明: 这种方法可能会破坏系统的正常
工作状态,因为temp是一个指针变量 b 59
但是在函数中并没有给temp一个确定 的地址,这样它所指向的内存单元是 不可预见的,而对*temp的赋值可能 带来危害
swap2 &a p1
&b p2 随机值 temp
5?
ppt课件
11
例 6. 3 ③ #include <stdio.h> void swap3( int *p1, int *p2) { int *p;
p
*p = 12 ; printf (“%d\n” , *p ) ;
对a 重新赋值 等价于 a=12
2. & 与*
p =ห้องสมุดไป่ตู้&a ;
1010 152 a
&*p &(*p) &a *&a *(&a) *p a
ppt课件
6
3. *与 ++ , - -
int a = 2 , b = 5 , c , d , *p ; (1) p = &a ;
② 形参表列: 即指针变量所指向的函数的形参表列 ③ 格式中的小括号不能省略 2. 应用 (1) 让指针变量指向函数 pt = add ; 因为函数名为函数的入口地址, 所以直接将函数名 赋给指针变量即可 (2) 使用指针变量调用函数 格式 : (*指针变量名) ( 实参表列)
ppt课件
17
例 求一维数组中全部元素的和
因此我们可以定义一个指针变量, 让它的值等于 函数的入口地址, 然后可以通过这个指针变量来调用 函数, 该指针变量称为指向函数的指针变量
ppt课件
16
指向函数的指针变量

C语言指针知识点总结

C语言指针知识点总结

C语⾔指针知识点总结1.指针的使⽤和本质分析(1)初学指针使⽤注意事项1)指针⼀定要初始化,否则容易产⽣野指针(后⾯会详细说明);2)指针只保存同类型变量的地址,不同类型指针也不要相互赋值;3)只有当两个指针指向同⼀个数组中的元素时,才能进⾏指针间的运算和⽐较操作;4)指针只能进⾏减法运算,结果为同⼀个数组中所指元素的下表差值。

(2)指针的本质分析①指针是变量,指针*的意义:1)在声明时,*号表⽰所声明的变量为指针。

例如:int n = 1; int* p = &n;这⾥,变量p保存着n的地址,即p<—>&n,*p<—>n2)在使⽤时,*号表⽰取指针所指向变量的地址值。

例如:int m = *p;②如果⼀个函数需要改变实参的值,则需要使⽤指针作为函数参数(传址调⽤),如果函数的参数数据类型很复杂,可使⽤指针代替。

最常见的就是交换变量函数void swap(int* a, int* b)③指针运算符*和操作运算符的优先级相同例如:int m = *p++;等价于:int m= *p; p++;2.指针和数组(1)指针、数组、数组名如果存在⼀个数组 int m[3] = {1,2,3};定义指针变量p,int *p = m(这⾥m的类型为int*,&a[0]==>int*)这⾥,其中,&m为数组的地址,m为数组0元素的地址,两者相等,但意义不同,例如:m+1 = (unsigned int)m + sizeof(*m)&m+1= (unsigned int)(&m) + sizeof(*&m)= (unsigned int)(&m) + sizeof(m)m+1表⽰数组的第1号元素,&m+1指向数组a的下⼀个地址,即数组元素“3”之后的地址。

等价操作:m[i]←→*(m+i)←→*(i+m)←→i[m]←→*(p+i)←→p[i]实例测试如下:1 #include<stdio.h>23int main()4 {5int m[3] = { 1,2,3 };6int *p = m;78 printf(" &m = %p\n", &m);9 printf(" m = %p\n", m);10 printf("\n");1112 printf(" m+1 = %p\n", m + 1);13 printf(" &m[2] = %p\n", &m[2]);14 printf(" &m+1 = %p\n", &m + 1);15 printf("\n");1617 printf(" m[1] = %d\n", m[1]);18 printf(" *(m+1) = %d\n", *(m + 1));19 printf(" *(1+m) = %d\n", *(1 + m));20 printf(" 1[m] = %d\n", 1[m]);21 printf(" *(p+1) = %d\n", *(p + 1));22 printf(" p[1] = %d\n", p[1]);2324return0;25 }输出结果为:(2)数组名注意事项1)数组名跟数组长度⽆关;2)数组名可以看作⼀个常量指针;所以表达式中数组名只能作为右值使⽤;3)在以下情况数组名不能看作常量指针:- 数组名作为sizeof操作符的参数- 数组名作为&运算符的参数(3)指针和⼆维数组⼀维数组的指针类型是 Type*,⼆维数组的类型的指针类型是Type*[n](4)数组指针和指针数组①数组指针1)数组指针是⼀个指针,⽤于指向⼀个对应类型的数组;2)数组指针的定义⽅式如下所⽰:int (*p)[3] = &m;②指针数组1)指针数组是⼀个数组,该数组⾥每⼀个元素为⼀个指针;2)指针数组的定义⽅式如下所⽰:int* p[5];3.指针和函数(1)函数指针函数的本质是⼀段内存中的代码,函数的类型有返回类型和参数列表,函数名就是函数代码的起始地址(函数⼊⼝地址),通过函数名调⽤函数,本质为指定具体地址的跳转执⾏,因此,可定义指针,保存函数⼊⼝地址,如下所⽰:int funcname(int a, int b);int(*p)(int a, int b) = funcname;上式中,函数指针p只能指向类型为int(int,int)的函数(2)函数指针参数对于函数int funcname(int a, int b);普通函数调⽤ int funcname(int, int),只能调⽤函数int func(int, int)函数指针调⽤ intname(*func)(int,int),可以调⽤任意int(int,int)类型的函数,从⽽利⽤相同代码实现不同功能,实例测试如下,假设有两个相同类型的函数func1和func2:1int func1(int a, int b, int c)2 {3return a + b + c;4 }56int func2(int a, int b, int c)7 {8return a - b - c;9 }普通函数调⽤和函数指针调⽤⽅式及结果如下所⽰1 printf("普通函数调⽤\n");2 printf("func1 = %d\n", func1(100, 10, 1));3 printf("func2 = %d\n", func2(100, 10, 1));4 printf("\n");56 printf("函数指针调⽤\n");7int(*p)(int, int, int) = NULL;8 p = func1;9 printf("p = %d\n", p(100, 10, 1));10 p = func2;11 printf("p = %d\n", p(100, 10, 1));12 printf("\n");需要注意的是,数组作为函数参数的时候,会变为函数指针参数,即:int funcname( int m[] )<——>int funcname ( int* m );调⽤函数时,传递的是数组名,即funcname(m);(3)回调函数利⽤函数指针,可以实现⼀种特殊的调⽤机制——回调函数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二重指针详解
朱有鹏
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 型的元素。

[0][0][0][1][0][2][0][3][0][4]
[1][0][1][1][1][2][1][3][1][4]
a[0]a[1]图数组为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]的值)。

相关文档
最新文档