C Primer plus 6中java双向链表实现接的实现中为什么用二级指针。这样的指针保存的是什么地址。求指点

Teach Yourself Programming in Ten Years
Powered by在编写链表相关的程序时,为了使程序的可移植性强的特点,建议在插入函数 传入的链表参数为二级指针型,这样该函的返回值定为void,便于接口访问。下面是我的部分程序代码:
#define ELEMENT_TYPE&int
typedef struct Node&L
struct Node
&ELEMENT_TYPE
&struct Node *
/* 插入元素到链表中,采用尾部插入的方法 */
void Insert(List** myList, ELEMENT_TYPE x)
&List* p = *myL
&List* tmp = NULL;
&tmp = (List*)malloc(sizeof (List) );
&if (NULL == tmp)
&&cout && &Application memory faliure& &&
&&exit(1);
&tmp-&element =
&tmp-&next = NULL;
&if (IsEmpty(p))
&&*myList =
&&while (NULL != p-&next)
&&&p = p-&
&&p-&next =
int main( void )
&List* g_myList = NULL;
&Insert(&g_myList, 1);
return 0;
1.为什么采用二级指针作为参数,这里涉及到了函数参数的问题:函数参数为变量,接收过来的只是变量的值,函数的变量有自己的内存空间,与实际参数的地址是不一样的,这就是为什么交换两个变量的值用值传递无法实现的原因。下面是一个说明
int a = 1;
Int b = 2;
Max(a, b);&&&&&Max函数在未调用之前,&&&&&&&&&
void Max(c, d); Max函数在未调用之前,c,d的值是随机值;调用之后,相当于把a的值赋给c,b的值赋给d;而a和c的地址空间是完全不一样的,同b和d的地址空间也是不一样的;大家可以用printf(&%d%d%d%d&, &a, &c, &b, &d);来验证一下,这样Max函数实际上是交换了两个局部变量的值。
2.对于指针参数
传递给函数参数的还是值,只不过这个值是指针变量的值,对指针变量*操作就是以这个值为地址,获取这个地址上存的数据,这样操作函数的局部变量相当于操作那两块地址空间了,这样就会实现上例中Max的功能了。
3.总以一句话,传递给函数参数的值都是一份拷贝,并不是原来的那个变量(除了引用类型),每个变量都有自己独一无二的地址空间;这样就不难理解,插入链表时传入二级指针参数的原因了。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:427次
排名:千里之外二级指针及链表操作中遇到的一点小问题
二级指针及链表操作中遇到的一点小问题
编辑:www.fx114.net
本篇文章主要介绍了"二级指针及链表操作中遇到的一点小问题",主要涉及到二级指针及链表操作中遇到的一点小问题方面的内容,对于二级指针及链表操作中遇到的一点小问题感兴趣的同学可以参考一下。
在编写链表相关的程序时,为了使程序的可移植性强的特点,建议在插入函数 传入的链表参数为二级指针型,这样该函的返回值定为void,便于接口访问。下面是我的部分程序代码:
#define ELEMENT_TYPE&int
typedef struct Node&L
struct Node
&ELEMENT_TYPE
&struct Node *
/* 插入元素到链表中,采用尾部插入的方法 */
void Insert(List** myList, ELEMENT_TYPE x)
&List* p = *myL
&List* tmp = NULL;
&tmp = (List*)malloc(sizeof (List) );
&if (NULL == tmp)
&&cout && &Application memory faliure& &&
&&exit(1);
&tmp-&element =
&tmp-&next = NULL;
&if (IsEmpty(p))
&&*myList =
&&while (NULL != p-&next)
&&&p = p-&
&&p-&next =
int main( void )
&List* g_myList = NULL;
&Insert(&g_myList, 1);
return 0;
1.为什么采用二级指针作为参数,这里涉及到了函数参数的问题:函数参数为变量,接收过来的只是变量的值,函数的变量有自己的内存空间,与实际参数的地址是不一样的,这就是为什么交换两个变量的值用值传递无法实现的原因。下面是一个说明
int a = 1;
Int b = 2;
Max(a, b);&&&&&Max函数在未调用之前,&&&&&&&&&
void Max(c, d); Max函数在未调用之前,c,d的值是随机值;调用之后,相当于把a的值赋给c,b的值赋给d;而a和c的地址空间是完全不一样的,同b和d的地址空间也是不一样的;大家可以用printf(&%d%d%d%d&, &a, &c, &b, &d);来验证一下,这样Max函数实际上是交换了两个局部变量的值。
2.对于指针参数
传递给函数参数的还是值,只不过这个值是指针变量的值,对指针变量*操作就是以这个值为地址,获取这个地址上存的数据,这样操作函数的局部变量相当于操作那两块地址空间了,这样就会实现上例中Max的功能了。
3.总以一句话,传递给函数参数的值都是一份拷贝,并不是原来的那个变量(除了引用类型),每个变量都有自己独一无二的地址空间;这样就不难理解,插入链表时传入二级指针参数的原因了。
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:二级指针学习心得 - 滴水成河 百川归海 - CSDN博客
二级指针学习心得
C语言基础知识
今天在修改以前写的代码的时候遇到了一个问题,我想通过timer_fresh_func 函数去修改指针*head指向的地址,但是,实际的结果是*head指向的地址并没有发生什么改变。在思考的时候我的脑中蹦出了二级指针这个东西。
void timer_fresh_func(user_timer_t *ctx, user_timer_t *node)
user_timer_t *head;
user_timer_
timer_fresh_func(head, &timer);
在我的理解中,指针在C语言中是一种特殊的数据类型,相较其他的数据类型(整型、浮点型等)来说,指针型量所保存的数据是其指向的变量(变量、函数等)在内存中的地址。*符号则是用于读取该地址所保存的数据,指针的类型决定了CPU从该地址中读取空间的大小。同理,二级指针也是指针,只不过它是一种指向指针的指针。
为什么在上面的程序中head所指向的地址最终没有改变,实际上原因十分简单。ctx在执行到ctx = 之前它指向的地址是head,在执行完ctx = 之后它指向的地址是node,在这中间只有ctx指向的地址发生了变化,与head并没有什么关系。
上面的那段程序等效于下面这段程序。
user_timer_t *ctx =
user_timer_t *node;
二级指针是一种能够指向指针的指针,然而它本身还是指针,二级指针所保存的数据是它所指向的指针在内存中的地址,而它所指向的指针保存的是其指向的变量在内存中的地址(有点像链表)。为了改变指针head所指向的地址,我们只需要修改二级指针所指向的一级指针所保存的数据(保存的变量地址)就能够改变head的地址了。所以程序只要修改成这样就能够完成目的了。理解了这些二级指针其实很简单!
void timer_fresh_func(user_timer_t **ctx, user_timer_t *node)
user_timer_t *head;
user_timer_
timer_fresh_func(&head, &timer);
我的热门文章由链表初始化看C语言的二级指针 - gmy的码农世界 - ITeye博客
博客分类:
先来看C语言创建链表、插入节点和遍历链表的一段代码:
#include &stdio.h&
#include &stdlib.h&
typedef int ElemT
typedef struct Node{
struct Node *
}Node, *LinkedL
//void init_linkedlist(LinkedList *list) {
void init_linkedlist(LinkedList *list) {
*list = (LinkedList)malloc(sizeof(Node));
(*list)-&next = NULL;
void insert(LinkedList list, ElemType elem) {
Node *p, *q;
p = (Node *)malloc(sizeof(Node));
p-&next = NULL;
while(q-&next != NULL) q = q-&
void main() {
LinkedList list,
init_linkedlist(&list);
insert(list, 3);
insert(list, 4);
insert(list, 5);
p = list-&
while(p != NULL) {
printf("%4d", p-&elem);
printf("\n");
这个小程序完成的功能很简单,创建一个链表,然后插入3,4,5这三个整数,最后遍历链表输出每个节点中的整数。但是大家注意到没有,在main函数中,初始化链表的函数参数的是一个二级指针,为什么要使用一个二级指针作为参数呢?在任何一本C语言的教材上,都会写C语言的函数参数传递是值传递方式,所有的参数都是通过值传递的,使用指针作为参数可以在函数中改变参数的值(此处感觉表达有误,但是想不到更好的表达方式)。可能有人会有疑问了,在上面代码的main函数中初始化链表的调用函数代码
init_linkedlist(&list);
list已经是一个指针了,为什么要传递一个指针的地址,直接使用指针不行吗?确实不行。
为什么?那么我们来看看不使用二级指针会发生什么情况,先来看看不使用二级指针的代码:
#include &stdio.h&
#include &stdlib.h&
typedef int ElemT
typedef struct Node{
struct Node *
}Node, *LinkedL
void init_linkedlist(Node *list) {
list = (LinkedList)malloc(sizeof(Node));
list-&next = NULL;
void insert(LinkedList list, ElemType elem) {
Node *p, *q;
p = (Node *)malloc(sizeof(Node));
p-&next = NULL;
while(q-&next != NULL) q = q-&
void main() {
LinkedList list,
printf("%d\n", list);
init_linkedlist(list);
printf("%d\n", list);
这段代码的main函数中有两处输出,分别是在初始化链表函数之前和之后,如果运行这段代码,会发现两处输出都是一样的值:
但是如果在使用二级指针的代码(本文的第一段代码)中插入相同的两处输出代码,会发现输出的两个值是不同的:
为什么会这样,原因就在于本文的第一段代码使用的是二级指针作为参数传递,而第二段代码使用的是一级指针作为参数传递。这个问题最终还是回归到了C语言参数传递是值传递了。
如果是使用一级参数传递,首先是main函数中定义一个Node类型的指针,这个指针用list表示,C语言在定义指针的时候也会分配一块内存,一般会占用2个字节或4个字节,现在在大部分的编译器中占用4个字节,这里用4个字节算。在这4个字节的内存中,没有任何值,所以这个指针不指向任何值。然后传递到函数init_linkedlist中,在init_linkedlist函数中,编译器首先为形参list分配一个临时指针内存块,而语句
list = (LinkedList)malloc(sizeof(Node));
中函数malloc分配一块内存,并向该程序返回一个指向这块内存的指针,这样形参list就有值了,在list所表示的临时内存区域中填入刚刚分配的内存的这块内存的地址,假设为0x10086,这样使用(*list)就可以访问这块内存(0x10086)中的内容了。此时在函数init_linkedlist中list所代表的这块内存中的内容是有值的,为0x10086,用图可表示为:
但是现在的list只是占据了一个零时的内存空间,这种改变并不能反映到main函数中,init_linkedlist函数执行完了,临时的list内存块就被回收了,这样刚刚分配的内存块的地址0x10086没有被记录下来。而我们如果要初始化main函数中的链表list的话,就必须记录记录下这块内存空间(0x10086)。
下面我们来考虑使用二级指针的代码,在使用二级指针的代码(本文第一段代码)中,首先定义了一个指针
LinkedList list
然后调用init_linkedlist,调用代码是
init_linkedlist(&list);
这样传递的参数就是一个指针的地址,在函数的参数列表中就表现为指针的指针,函数的定义为
void init_linkedlist(LinkedList *L)
函数的参数是一个二级指针,同样,在执行调用这个函数的时候,临时分配一个指针,这个指针占据一个占用4个字节的内存块(函数执行完要回收的),同时这个临时指针L指向主函数main中定义的list指针,这里假设主函数main中的list指针在内存中的地址为0x12306,用图表示为
其中L是一块临时内存,list是主函数main的中定义的一个指针,此时list代表的内存块中还没有内容(貌似这样说法有误,或者说这块内存还没有初始化)。下面执行内存分配的代码
*L = (LinkedList)malloc(sizeof(Node));
malloc函数分配了一块内存空间,假设地址为0x10010,由于L指向list所代表的内存块,所以*L等价于list,这样将malloc函数分配的内存块赋值给*L就相当于执行语句
list = 0x10010
那么在list代表的内存块中所存储的值就为0x10010,用图表示为
这样在函数init_linkedlist中分配的一段内存也就能在main函数中反映出来了,main函数中list代表的内存块的就指向了新分配的内存,链表初始化完成。
guimingyue
浏览: 49523 次
来自: 湖北
POI获取到xlsx文件中的数据和获取xls文件中的数据代码肯 ...
感谢!这是我看了几个回答里最清楚的一个!
看错了,请楼主删回帖
非常不错,不过函数init_linkedlist中的二级指针参 ...
总结得挺好的,我遇到过这样的问题,后来发现是form的enct ...

我要回帖

更多关于 数组实现链表 的文章

 

随机推荐