精华内容
下载资源
问答
  • 1.二重指针 (1)二重指针与普通一重指针的区别 ->本质上来说,二重指针和一重指针的本质都是指针变量,指针变量的本质就是变量。 ->一重指针变量和二重指针变量本身都占4字节内存空间。 ...

    1.二重指针

    (1)二重指针与普通一重指针的区别

    ->本质上来说,二重指针和一重指针的本质都是指针变量,指针变量的本质就是变量。

    ->一重指针变量和二重指针变量本身都占4字节内存空间。

    (2)二重指针的本质

    ->二重指针本质上也是指针变量,和普通指针的差别就是它指向的变量类型必须是个一重指针

    (3)二重指针的用法: 

    二重指针指向一重指针的地址.:

    	char a;
    	char **p1;		// 二重指针
    	char *p2;		// 一重指针
    	
    	printf("sizeof(p1) = %d.\n", sizeof(p1));    //4
    	printf("sizeof(p2) = %d.\n", sizeof(p2));     //4
    	
    	p2 = &a;
    	//p1 = &a;		// p1是char **类型,&a是char *类型。
    					// char **类型就是指针指向的变量是char *类型
    					// char *类型表示指针指向的变量是char类型。
    	p1 = &p2;		// p2本身是char *类型,再取地址变成char **类型,和p1兼容。
    

    二重指针指向指针数组:

    int *p1[5];	
    int **p3;
    p3 = p1;		// p1是指针数组名,本质上是数组名,数组名做右值表示数组首元素
    				// 首地址。数组的元素就是int *类型,所以p1做右值就表示一个int *
    				// 类型变量的地址,所以p1就是一个int类型变量的指针的指针,所以
    				// 它就是一个二重指针int **;
    

    实践编程中有时在函数传参时为了通过函数内部改变外部的一个指针变量,会传这个指针变量的地址(也就是二重指针)进去

    void func(int **p)
    {
    	*p = (int *)0x12345678;
    }
    
    int main(void)
    {
    	int a = 4;
    	int *p = &a;				// p指向a
    	printf("p = %p.\n", p);		// p打印出来就是a的内存地址
    	func(&p);					// 在func内部将p指向了别的地方
    	printf("p = %p.\n", p);		// p已经不指向a了,所以打印出来不是a的地址
    	*p = 23;					// 因为此时p指向0x12345678,但是这个地址是不
    								// 允许访问的,因此会段错误。
    	return 0;
    }
    


    2.二维数组

    (1)二维数组的内存映像:

     

    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]
    

    ->一维数组在内存中是连续分布的多个内存单元组成的,而二维数组在内存中也是连续分布的多个内存单元组成的。

    ->从内存角度来看,一维数组和二维数组没有本质差别。二维数组int a[2][5]和一维数组int b[10]其实没有任何本质差别。我们可以把两者的同一单元的对应关系写下来。

    ->二维数组a和一维数组b在内存使用效率、访问效率上是完全一样的(或者说差异是忽略不计的)。

    ->在某种情况下用二维数组而不用一维数组,原因在于二维数组好理解、代码好写、利于组织(比如图片的显示)。

    (2)哪个是第一维哪个是第二维:

    ->二维数组int a[2][5]中,2是第一维,5是第二维。

    ->二维数组的第一维是最外部的那一层第一维本身是个数组,这个数组中存储的元素也是个一维数组二维数组的第二维是里面的那一层,第二维本身是个一维数组,数组中存的元素是普通元素,第二维这个一维数组本身作为元素存储在第一维的二维数组中。

    (3)二维数组的下标式访问和指针式访问 

    ->回顾:一维数组的两种访问方式:

    以int b[10]为例, int *p = b;。
    b[0] 等同于 *(p+0);   b[9] 等同于 *(p+9);  b[i] 等同于 *(p+i)
    

    ->二维数组的两种访问方式:

    以int a[2][5]为例,(合适类型的)p = a;
    a[0][0]等同于*(*(p+0)+0); 	a[i][j]等同于 *(*(p+i)+j)
    

    (4)指针指向二维数组的数组名

    ->二维数组的数组名表示二维数组的第一维数组中首元素(也就是第二维的数组)的首地址,即为数组指针(数组的地址)

    ->二维数组的数组名a等同于&a[0],这个和一维数组的符号含义是相符的。

    (5)指针指向二维数组的第一维

    ->用int *p来指向二维数组的第一维a[i],就是一个一维的指针。

    (6)指针指向二维数组的第二维

    #include <stdio.h>
    
    int main(void)
    {
    	int a[2][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
    	
    	printf("a[1][3] = %d.\n", a[1][3]);       //9
    	printf("a[1][3] = %d.\n", *(*(a+1)+3));   //9
    	
    	//int *p1 = a;		// 类型不匹配
    	//int **p2 = a;		// 类型不匹配,会报警告
    	
    	// 指针指向二维数组的数组名
    	int (*p3)[5];		// 数组指针,指针指向一个数组,数组有5个int类型元素
    	p3 = a;				// a是二维数组的数组名,作为右值表示二维数组第一维的数组
    						// 的首元素首地址,等同于&a[0]
    	p3 = &a[0];
    	
    	printf("a[0][3] = %d.\n", *(*(p3+0)+3));      //4
    	printf("a[1][4] = %d.\n", *(*(p3+1)+4));      //10
    	
    	// 指针指向二维数组的第一维
    	//int *p4 = &a[0];		// 不可以
    	int *p4 = a[0];			// a[0]表示二维数组的第一维的第一个元素,相当于是
    							// 第二维的整体数组的数组名。数组名又表示数组首元素
    							// 首地址,因此a[0]等同于&a[0][0];
    	
    	int *p5 = &a[0][0];	
    	printf("a[0][4] = %d.\n", *(p4+4));     //5
    
    	// 指向二维数组的第二维
    	int *p6 = a[1];
    	printf("a[1][1] = %d.\n", *(p6+1));     //7
    
    	return 0;
    }
    

    展开全文
  • 二重指针的使用

    2021-07-19 20:44:12
    1、为什么会在传参的时候用二重指针呢? 要想弄明白这个问题,先搞清楚为什么传参的时候用指针? 我想很多人都知道直接传值是不会改变实参的值的,只能改变形参的值。所以我们把参数设定为地址,即、传参时用指针...

    1、为什么会在传参的时候用二重指针呢?

    要想弄明白这个问题,先搞清楚为什么传参的时候用指针?

    我想很多人都知道直接传值是不会改变实参的值的,只能改变形参的值。所以我们把参数设定为地址,即、传参时用指针,我们就可以改变实参的值。

    2、那么考虑一下另外一种情况,我们如果想要改变的实参是一个地址呢?那我们直接把地址值作为形参传进去,函数是不会改变实参(地址值)的。那我们想要改变这个地址值,要怎么办呢?

    照葫芦画瓢呗!我们知道指针(地址)也是变量,它也存在一个地址中,所以我们把存指针的地址(二重指针)作为形参传进去,就可以改变指针值了。

    3、为什么需要传二重指针呢?

    当然是为了改变地址值啦,试想一下,某种情况下,我们要动态申请5个字节的内存

            char* p = (char*)malloc(5);

    可是过了一段时间发现5个字节不够用了啊。想扩大到10个字节,那怎么办呢?有的人说再申请5个呗。可是我想用一个变量对这10个字节的地址进行访问。。

    所以我们可以封装一个函数,用来扩大字节数。

    那么这个函数怎么写呢?我想这个函数的逻辑结构是不是应该是这样的:

            1、在函数体内申请10个字节, char* q = (char*)malloc(10);

            2、把p,这5个字节里面的内容拷贝到q里面,再把q的地址返回去

    那么假如我们利用函数参量进行返回(不利用函数类型返回),那么我们需要把传进来的p地址换成q的地址。那么怎么改变实参呢?不就正好是把存p的地址传进去么?!

    4、二重指针在单链表中的应用

            1、节点定义

                  

            2、创建头指针

                    

            3、创建单链表

            在主函数中创建头指针List,但是是指向NULL,我们希望它指向头结点,在单链表构建函数中,我们malloc一个头结点,并把List的指向改为指向malloc的地址。这样实参就被我们改变了,在主函数中就可以用这个地址进行访问了。

            当然你也可以把返回值void改为Linklist,这样利用返回值去指向头结点也可以。

     

     

     

    展开全文
  • c++二重指针

    2020-10-27 17:15:17
    int *aaaa =nullptr;... n 为一个二重指针,指向aaaa(aaaa为一个int类型指针) 或者说 n存储aaaa的地址 *n 取地址指向的对象,即aaaa;(aaaa存储了一个int类型的地址) **n 读取aaaa所指向的对象,即int类型的1
    int *aaaa =nullptr;
    	aaaa = new int;
    	*aaaa = 1;
    	cout << &aaaa<<" "<<aaaa << "  " << *aaaa << endl;;
    	//delete aaaa;
    	int **n = &aaaa;
    	cout << n << "  " << *n << "  " << **n << "   ";
    

    结果如下:
    在这里插入图片描述
    结论:n=&aaaa; *n=aaaa; **n=aaaa;
    n
    为一个二重指针,指向aaaa(aaaa为一个int类型指针)
    或者说 n存储aaaa的地址

    *n
    取地址指向的对象,即aaaa;(aaaa存储了一个int类型的地址)

    **n
    读取aaaa所指向的对象,即int类型的1

    展开全文
  • C语言中指针的理解5:二重指针与二维数组1.二重指针1.1 二重指针与普通一重指针的区别1.2 二重指针的用法1.3 一些概念的实质2.二维数组2.1 二维数组的内存映像2.2 二维数组下标理解和访问2.3 二维数组的应用和更多维...

    1.二重指针

    1.1 二重指针与普通一重指针的区别

    本质上来说,二重指针和一重指针的本质都是指针变量,占用相同的内存空间,而指针变量的本质就是变量。

    二重指针本质上也是指针变量,和普通指针的差别就是它指向的变量类型必须是个一重指针。二重指针其实也是一种数据类型,编译器在编译时会根据二重指针的数据类型来做静态类型检查,一旦发现运算时数据类型不匹配编译器就会报错。

    C语言其实是可以没有二重指针的。一重指针完全可以做二重指针做的事情,之所以要发明二重指针(以及函数指针、数组指针),之所以要区分这些指针,就是为了让编译器了解这个指针被定义时,定义它的程序员希望这个指针被用来指向什么东西,定义指针时用数据类型来标记,比如int *p就表示p要指向int型数据。编译器知道指针类型之后可以帮我们做静态类型检查,这种静态类型检查可以辅助程序员发现一些隐含性的编程错误,这是C语言给程序员提供的一种编译时的查错机制。

    1.2 二重指针的用法

    二重指针必须指向一重指针的地址,例如:

    int main(int argc,char**argv)
    {
    	int a =5;
    	int*p1 = &a;	//p1是一重指针,它指向a,保存的是int变量a的地址
    	int** p2 = &p1;	//p2是二重指针,它指向p1,保存的是指针变量p1的地址
    
    	return 0;
    }
    

    二重指针也可以指向指针数组的地址:

    int main(int argc,char**argv)
    {
    	int*p1[5] = {};	//p1是指针数组,即内部元素都是一重指针的数组
    	int** p2 = p1;	//p1作右值的时候是二重指针
    
    	return 0;
    }
    

    对于指针数组p1,做右值的时候它是数组首元素的地址,也就是说它指向数组首元素,而这是一个指针数组,数组首元素就是一个一重指针,所以p1是一个指向一重指针的指针,也就是二重指针,所以可以直接做右值赋值给p2

    实际应用中二重指针用的比较少,大部分时候就是和指针数组纠结起来用的。有时在函数传参时为了通过函数内部改变外部的一个指针变量,会传这个指针变量的地址,也就是二重指针进去。

    1.3 一些概念的实质

    首先还是要明确:二重指针、数组指针、结构体指针、一重指针、普通变量,这些的本质都是相同的,它们都是变量,和一段内存空间绑定,空间内会存入数据。

    所有的指针变量本质也都是相同的,64位机器中都是8个字节,用来指向别的变量,不同类型的指针变量只是可以指向的,或者说编译器允许指向的变量类型不同。

    二重指针大部分情况下就是用来指向指针数组的。

    2.二维数组

    2.1 二维数组的内存映像

    一维数组在内存中是连续分布的多个内存单元组成的,而二维数组在内存中实际上也是由连续分布的多个内存单元组成的。从内存角度来看,一维数组和二维数组没有本质差别。二维数组int a[2][3]和一维数组int b[6]在内存中的存储方式其实没有任何本质差别。

    举个栗子:

    #include<stdio.h>
    
    int main(int argc,char**argv)
    {
    	int b[6]={0};
    	int a[2][3];
    	for(int i=0;i<6;++i)
    		printf("%p ",&b[i]);
    	printf("\n");
    	
    	for(int i=0;i<2;++i)
    		for(int j=0;j<3;++j)
    			printf("%p ",&a[i][j]);
    	
    	printf("\n");
    	return 0;
    }
    

    输出:

    0x7ffe4a7f1ad0 0x7ffe4a7f1ad4 0x7ffe4a7f1ad8 0x7ffe4a7f1adc 0x7ffe4a7f1ae0 0x7ffe4a7f1ae4 
    0x7ffe4a7f1af0 0x7ffe4a7f1af4 0x7ffe4a7f1af8 0x7ffe4a7f1afc 0x7ffe4a7f1b00 0x7ffe4a7f1b04 
    

    既然二维数组都可以用一维数组来表示,那二维数组存在的意义和价值在哪里?二维数组a和一维数组b在内存访问效率上是完全一样的,或者说差异是忽略不计的。在某种情况下用二维数组而不用一维数组,原因在于二维数组好理解,代码好写而且利于组织。

    总结:使用C语言提供二维数组并不是必须的,而是一种简化编程的方式。其实一维数组的出现其实也不是必然的,也是为了简化编程。

    2.2 二维数组下标理解和访问

    二维数组int a[2][3]中,2是第一维,3是第二维。结合内存映像来理解二维数组的第一维和第二维的意义:首先第一维是最外面一层的数组,所以int a[2][3]这个数组有2个元素,其中每一个元素又是一个含有3个元素的一维数组,这个数组就是第二维。

    总结:

    • 二维数组的第一维是最外部的那一层,第一维本身是个数组,并且这个数组中存储的元素也是个一维数组。
    • 二维数组的第二维是里面的那一层,第二维本身是个一维数组,数组中存的元素是普通元素,第二维这个一维数组本身作为元素存储在第一维的二维数组中。

    一维数组有数组下标和指针偏移运算两种访问方式,以int b[6]为例:

    int *p = b;。
    b[0]=5//b[0]等同于 *(p+0);   
    b[9]=6; //b[9]等同于 *(p+9);  b[i] 等同于 *(p+i)
    

    二维数组同样有两种访问方式,以int a[2][3]为例:

    int (*p)[3];
    p= a;
    a[0][0]=3; //a[0][0]等同于*(*(p+0)+0); 	
    a[1][4]=3; //a[1][4]等同于*(*(p+1)+4); a[i][j]等同于 *(*(p+i)+j)
    

    int a[2][3]是一个二维数组,其实它内部也是两个元素,只不过这两个元素也是数组,而数组名a是指向第一个元素:一个大小为3的int型数组的,所以a的类型是一个数组指针,它首先是一个指针,指向一个大小为3的int型数组,根据之前 [C语言指针的理解二:指针与数组、数组指针与指针数组] 中数组指针的定义和理解方法,就可以得到数组指针p的定义语法为:int (*p)[3];

    2.3 二维数组的应用和更多维数组

    最常用情况:一维数组用来表示一个线性表,二维数组用来表示一张单通道灰度图像,三维数组可以表示三通道的RGB图像等。四维数组也是可以存在的,在数学上有意义,现实空间中没有对应,因为人类生存的宇宙是三维的。

    总结:一般常用最多就到三维数组,四维数组除了做一些特殊与数学运算有关的之外基本用不到。

    2.4二维数组的运算和指针

    1.指针指向二维数组的数组名:二维数组的数组名表示二维数组的第一维数组中首元素,也就是第二维的数的首地址。二维数组的数组名a等同于&a[0],这个和一维数组的符号含义是相符的,用数组指针来指向二维数组的数组名是类型匹配的,通过该指针可以访问整个二维数组元素。

    #include<stdio.h>
    
    int main(int argc,char**argv)
    {
    	int a[2][3]={{1,2,3},{4,5,6}};
    	int (*p)[3] = a;
    	for(int i=0;i<2;++i)
    	{
    		for(int j=0;j<3;++j)
    			printf("%d ",*(*(p+i)+j));
    		printf("\n");
    	}
    	
    	return 0;
    }	
    

    输出:

    1 2 3
    4 5 6
    

    2.指针指向二维数组的第一维:前面的分析可以知道,第一维就是一个数组,例如a[0]实际上就是{1,2,3}a[1]实际上就是{4,5,6}所以可以直接用int *p来指向二维数组第一维的各个元素a[i],通过该指针仅能访问二维数组的某一行元素。

    #include<stdio.h>
    
    int main(int argc,char**argv)
    {
    	int a[2][3]={{1,2,3},{4,5,6}};
    	int *p1 = a[0];
    	int* p2 = a[1];
    
    	for(int i=0;i<3;++i)
    		printf("%d ",p1[i]);
    	printf("\n");
    	
    	for(int i=0;i<3;++i)
    		printf("%d ",p2[i]);
    	printf("\n");
    	
    	return 0;
    }	
    

    输出:

    1 2 3
    4 5 6
    

    3.指针指向二维数组的第二维:二维数组的第二维元素其实就是普通变量了,例如a[1][1]其实就是int类型的4,已经不能用指针类型和它相互赋值了。除非int *p = &a[i][j];,类似于指针指向普通int型变量。

    2.5 总结

    理解二维数组和指针的关键就是2点:

    • 1.数组中各个符号的含义。
    • 2.数组的指针式访问,尤其是二维数组的指针式访问。
    展开全文
  • 二重指针

    2020-01-28 13:22:08
    一、二重指针的本质 二重指针与一重指针本质上都是指针变量,指针变量的本质也就是变量,都是用来指向别的东西的,在32位机上都是占4字节内存空间 二重指针指向的变量类型是一个一重指针 1.1 测试代码段 int a = ...
  • 指针和引用的关系 以及二重指针和指针引用 这里写目录标题指针和引用的关系 以及二重指针和指针引用指针和引用的概念指针和引用关系指针引用和二重指针 指针和引用的概念 平常写代码的时候大家多用到指针,却很少...
  • //二重函数指针 init_fnc_t *init_sequence[] = { //函数指针数组 cpu_init, /* basic cpu dependent setup */ board_init, /* basic board dependent setup */ interrupt_init, /* set up exceptions
  • C语言 二重指针

    千次阅读 2019-03-27 22:05:24
    #include <stdio.h> #include<string.h> int main(int argc, char *argv[]) ... //二级指针前面加1个*,代表一级指针的值 *pp == &a; //二级指针前面加2个*,代表一级指针指向的值 ...
  • 2)不论指针变量指向的是何种变量,对于指针变量来说所占字节都是一样的, 例如: int *p 和double *q, p和q都是占4个字节, 不同的是,p++ 和q++,前者挪动了4个字节,后者挪动了8个字节 3)指针变量存的是个...
  • 指针数组和数组指针的区别以及二维数组和数组指针的关联参见本文。 1)数组指针可以用来指向一个二维数组,如下所示: char ch[2][6] = {"hello","world"}; char (*str)[6] = ch;//将二维数组的首元素的地址付给...
  • 一个实例搞懂二重指针 最近在编写一个链表的时候遇到了关于指针的一些问题,在研究的过程中终于弄懂了在函数形参中使用二重指针的意义和用法。 我们先从编写一个函数说起。这个函数要求在一个链表的头部插入一个节点...
  • 如果已经定义了一个指针类型,我们再定义一个指针,用于指向已经定义的指针变量,后面定义的指针变量就是一个指向指针指针变量,简称指向指针指针,这样的指针也称二重(级)指针。 一、一般情况的例子: #...
  • 数组指针指针数组从字面上来看很纠结,有时候我也搞不清,分不清哪样的是数组指针,哪样的是指针数组。这东西就不是靠记忆的,我们采取分析加对比分层剥离的方法分析。 1.概念区别 1.1.数组指针: 定语在前,主语...
  • 二重指针的应用场景

    2019-12-12 10:26:36
    当指针作为参数传递的时候,两种情况需要使用二重指针: 改变指针所指向的地址,比如如下例子: #include <stdio.h> void change(char *v) { v = "bbb"; } int main(int argc, char *argv[]) { char *p =...
  • 二重指针的理解

    千次阅读 2018-12-02 15:48:58
    二重指针一般用的场合: (1)二重指针指向一重指针的地址。 #include&lt;stdio.h&gt; int main() { int a = 10; int *P1; int **P2; P1 = &amp;a; P2 = &amp;P1; return 0; }   (2)...
  • 今天看到结构体的二重指针的使用,有点迷糊,于是百度下,了解了。 1、结构体的定义 typedef struct Node { int data; struct Node *Next; }Point_T,*Point_P; 这里还需要理解下typedef的用法 Node为...
  • 两个结果相等:再次验证二重指针传参可以等价于指针数组。 1 #include <stdio.h> 2 3 void fun(char **arr,int n)//二重指针传参 4 { 5 int i; 6 for(i=0;i;i++) 7 printf("%s\n",arr[i]); 8 } 9 ...
  • C++二重指针理解

    2019-11-11 17:15:17
    做算法题的时候经常会碰到二重指针,看着非常别扭,于是自己敲了一下代码来理解一下这个概念。 int main() { int a = 1; int b = 2; int*p1 = &a; int*p2 = &b; p2 = p1; int**q = &p1; printf...
  • C语言函数传递指针的理解 传递参数时会生成一个复制的指针,该指针指向的位置与 原指针指向的位置相同; 即b自身在计算机的地址与a的地址不是相同的,这时你在函数体内修改a指向的位置,一定不会修改b指向的位置。 ...
  • 链表为什么有些情况下要使用二重指针

    千次阅读 多人点赞 2020-01-05 21:28:48
    链表 一个疑问 今天在复习链表时遇见了几个问题,其实是拖了很久的问题,现在尝试分析一下 结构体: typedef ... 关于二重指针可以接着看这篇加强理解:https://blog.csdn.net/qq_39579087/article/details/104812065
  • 函数内部修改外部一重指针变量的值,需要二重指针传递一重指针自身的地址; 如果传递变量的值或者一重指针的值,函数内部则会新建临时变量接收值,而无法改变外部变量的值。 参考博客 1、函数传参之变量与一重指针 ...
  • #include<iostream> using namespace std; int main() { int a[3][4]; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 4; ++j) a[i][j] = i + j; } int** p;... for (in.
  • 第16行将指针(*A)指向指针B //注意A是一个二重指针,所以将(*A)看成一个整体就是一重指针,也就是将二重指针进行 一次解引用就变成了一重指针 第15行打印(**A) //**A就是两次解引用后,变成了变量的数组...
  • ---指针数组与数组指针 (1)指针数组的实质是一个数组,这个数组中存储的内容全部是指针变量。 (2)数组指针的实质是一个指针,这个指针指向的是一个数组。 int *p[5]; int (*p)[5]; int *(p[5]); 总结:(第一步:找...
  • 函数指针、二重指针 1.指针数组与数组指针 1.1、字面意思来理解指针数组与数组指针 (1)指针数组的实质是一个数组,这个数组中存储的内容全部是指针变量。 (2)数组指针的实质是一个指针,这个指针指向的是一个数组。 ...
  • C语言二重指针与二维数组

    千次阅读 2019-07-23 21:51:28
    因为二维数组是数组的数组,又因为啊a[0]、a[1]、a[2]为三个数组的首地址(等同于&a[0][0]、&a[1][0]、&a[2][0]),所以当我们用二重指针创建数组的时候,实际上是创建了一个指针数组。 #include #include ...
  • C指针之二重指针

    2020-06-16 12:26:45
    二重指针 二重指针与普通一重指针的区别 本质上来说,二重指针和一重指针的本质都是指针变量,指针变量的本质就是变量。 一重指针变量和二重指针变量本身都占4字节内存空间 char a; char **p1; // 二重...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,697
精华内容 1,478
关键字:

二重指针