退出此函数后,为什么指针变量的值没有传递给指针参数?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了退出此函数后,为什么指针变量的值没有传递给指针参数?相关的知识,希望对你有一定的参考价值。
根据我目前对C如何工作的了解,如果我以这种方式使用函数List_int_add(linklist, 50)
而不必分配linklist = List_int_add(linklist, 50)
,则linklist的值将被更新为List_int_add(linklist, 50)
的返回值,因为代替linklist
是Node_int * head
的参数,该函数返回head
。由于参数是一个指针,不应该List_int_add(linklist, 50)
足以更新linklist
?
当使用List_int_add(linklist, 50)
时,List_int_print(linklist)
的输出将从100开始,而不是50.但如果我分配给linklist=List_int_add(linklist, 50)
,它的工作正常。
(请在返回时忽略类型转换,这是由于我以前编写代码的方式,我正在编辑代码,我知道没有必要)
提前致谢。
在main.c中:
#include <stdio.h>
#include <stdlib.h>
#include "LinkedList/linkedlist.h"
int main(int argc, char ** argv){
Node_int * linklist = NULL;
linklist = List_int_add(linklist, 50);
linklist = List_int_add(linklist, 100);
linklist = List_int_add(linklist, 150);
linklist = List_int_add(linklist, 200);
linklist = List_int_add(linklist, 250);
linklist = List_int_add(linklist, 300);
linklist = List_int_add(linklist, 350);
linklist = List_int_remove(linklist,50);
List_int_print(linklist);
List_int_destroy(linklist);
if (linklist == NULL)
List_int_print(linklist);
return EXIT_SUCCESS;
}
在链接list.c中:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "linkedlist.h"
/* Node_int_construct: create a Node_int */
static Node_int * Node_int_construct(int val);
/* Node_int_construct: create a Node_int */
static Node_int * Node_int_construct(int val){
Node_int * nd = (Node_int *) malloc(sizeof(Node_int));
nd->next = NULL;
nd->prev = NULL;
nd->value = val;
return nd;
}
Node_int * List_int_add(Node_int * head, int val){
Node_int * nd = Node_int_construct(val);
// insert at the end
Node_int * ptr = (Node_int *) head;
if (ptr == NULL){
head = nd;
head -> next = NULL;
head -> prev = NULL;
return (Node_int *) head;
}
while (ptr->next != NULL){
ptr = ptr->next;
}
nd->prev = ptr;
ptr->next = nd;
return (Node_int *) head;
}
Node_int * List_int_remove(Node_int * head, int val){
Node_int * target = List_int_search((const Node_int * const) head, val);
if (target == NULL){
return target;
}
if (target == head){
head = head->next;
head->prev = NULL;
free(target);
}
else if (target->next == NULL){
Node_int * ptr = target->prev;
ptr->next = NULL;
free(target);
}
else {
Node_int * prev = target->prev;
Node_int * next = target->next;
prev->next = next;
next->prev = prev;
free(target);
}
return head;
}
void List_int_destroy(Node_int * head){
Node_int * ptr = head;
Node_int * temp;
while (ptr != NULL){
temp = ptr;
ptr = ptr->next;
free(temp);
}
}
Node_int * List_int_search(const Node_int * const head, int val){
Node_int * ptr = (Node_int *) head;
while (ptr != NULL){
if (ptr->value == val){
return ptr;
}
ptr = ptr->next;
}
return ptr;
}
void List_int_print(const Node_int * const head){
Node_int * ptr = (Node_int*) head;
while (ptr != NULL){
printf("> %d
", ptr->value);
ptr = ptr->next;
}
}
在linkedlist.h中:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
typedef struct _node_int {
struct _node_int * next;
struct _node_int * prev;
int value;
} Node_int;
/* List_int_add: add Node_int at the end of list. */
Node_int * List_int_add(Node_int * head, int val);
/* List_int_remove: remove first item that matches val.
Returns head if successful, returns NULL if failure */
Node_int * List_int_remove(Node_int * head, int val);
/* List_int_destroy: Delete entire list. */
void List_int_destroy(Node_int * head);
/* List_int_search: Returns pointer to node of the first matching item in list,
NULL if node is not found. */
Node_int * List_int_search(const Node_int * const head, int val);
/* List_int_print: print int list. */
void List_int_print(const Node_int * const head);
#endif
为了确保没有任何误解,我将陈述一些我认为你已经知道的事情,但这只是为了澄清答案。
- C中的所有内容都是按值传递的。这意味着无论何时为函数赋予参数,实际给出的是该参数的副本(具有参数值的自动变量)。
- 为了能够使用函数修改变量
x
的值而不影响x
的返回值(例如.x=modify_x_please(x)
),我们将传递x的引用。这样,函数接收x
地址的副本,这使它能够通过解除引用来直接修改qazxs。
例如 :
x
将以这种方式使用:
void increment_int(int *x){
(*x)++;
}
所以你已经知道了以上所有内容,但让我们想象最后一个例子:
int x=3;
increment_int(&x);
/*here x is equal to 4*/
用法:
void set_pointer_to_null(void **p){
(*p)=NULL;
}
在这里,它与您的问题变得更加相关:如果要修改指针,则传递对指针的引用。
这意味着将您的函数签名更改为int * p;
p=&x;
set_pointer_to_null(&p);
/*p is NULL here*/
,并使用Node_int * List_int_add(Node_int ** head, int val)
而不是(*head)
等...
你甚至可以有一个head
,所以这个想法变得更加清晰。这样你可以想:如果我想修改一个列表,我会传递这个列表的地址。列表只是节点的地址这一事实是完全不同的事情。但我知道有反对“过度使用”typedef的论据,所以我认为你应该考虑使用我提出的typedef的缺点,如果你感兴趣的话。
最后一件事,如果添加和删除函数获得良好的引用并很好地修改它们,您甚至可能不需要返回。你可以让他们的返回类型为void。
您的笔记没有错,但它们不适用您显示的链接列表实现。 在这个答案的最后(讨论后),你会发现一个稍微改变的答案,你的笔记适用于这个答案。
您观察到所示代码的输出以100开头。
typedef Node_int * Linked_List_int_t
这是因为> 100
> 150
> 200
> 250
> 300
> 350
。
为了讨论为什么50不可见,重点关注指针作为参数的使用,请注意,如果删除该行,则从50开始。
List_int_remove(linklist,50);
删除除第一个//linklist = List_int_remove(linklist,50);
> 50
> 100
> 150
> 200
> 250
> 300
> 350
以外的所有内容仍然从50开始。
linklist =
第一个是因为linklist = List_int_add(linklist, 50);
/* linklist = */ List_int_add(linklist, 100);
/* linklist = */ List_int_add(linklist, 150);
/* linklist = */ List_int_add(linklist, 200);
/* linklist = */ List_int_add(linklist, 250);
/* linklist = */ List_int_add(linklist, 300);
/* linklist = */ List_int_add(linklist, 350);
> 50
> 100
> 150
> 200
> 250
> 300
> 350
以及列表不使用未打印的虚拟元素作为锚点的事实。实现链接列表的方法是您的注释适用的方法,请参阅下文。
如果第一个也被删除,则输出为空。
可以根据您的笔记使用链接列表,即始终只使用
Node_int * linklist = NULL;
没有List_int_add(linklist, 50)
,如果你改为使用锚。
下面的实现略有不同(更改标记为“//注意此更改!”)。
请注意,我保留了返回值,实际上不需要它们,但Node_int_construct(...)除外。如果严格忽略返回值,则使用NULL作为linklist参数是一个错误条件,我只是通过在错误消息之后直接返回来处理。 我将所有内容都放在一个文件中,作为一个方便的MCVE。
linklist =
以上是关于退出此函数后,为什么指针变量的值没有传递给指针参数?的主要内容,如果未能解决你的问题,请参考以下文章