C:处理指针的方法
我想知道为什么第一种方法不起作用,但第二种方法不起作用:
//第一种方法
int create_node(struct node *create_me, int init){ create_me = malloc(sizeof(struct node)); if (create_me == 0){ perror("Out of momory in ''create_node'' "); return -1; } (*create_me).x = init; (*create_me).next = 0; return 1; } int main( void ){ struct node *root; create_node(root, 0); print_all_nodes(root); }
好的,这里的print_all_nodes函数告诉我,root还没有被初始化。 现在第二种方法很好:
struct node* create_node(struct node *create_me, int init){ //<------- create_me = malloc(sizeof(struct node)); if (create_me == 0){ perror("Out of momory in ''create_node'' "); exit(EXIT_FAILURE); } (*create_me).x = init; (*create_me).next = 0; return create_me; //<--------- } int main( void ){ struct node *root; root = create_node(root, 0); //<--------------- print_all_nodes(root); }
在我的理解中(谈论方法1),当我给create_node
函数指向根节点的指针时,它实际上改变了x
和next
root。
就像你这样做:
void change_i(int* p){ *p = 5; } int main( void ){ int i = 2; printf("%d\n", i); change_i(&i); printf("%d", i); }
它实际上改变了i
。 明白了吗? 有人可以和我分享他/她的知识!
你需要一个指向指针的指针,而不仅仅是一个指针。
如果要在另一个函数中更改变量,则必须发送指向该变量的指针。 如果变量是整数变量,则发送指向该整数变量的指针。 如果变量是指针变量,则发送指向该指针变量的指针。
你在问题中说“当我给create_node
函数指向根节点的指针时,它实际上改变了x
和root的next
。” 你的措辞让我怀疑这里有一些混乱。 是的,您正在更改x
和next
的内容,但不更改root
。 root
没有x
和next
,因为root
是指向包含x
和next
的结构的指针。 您的函数不会更改root
的内容,因为您的函数获取的只是该指针的副本 。
您的代码更改:
int create_node(struct node **create_me, int init) { *create_me = malloc(sizeof(struct node)); if (*create_me == 0){ perror("Out of momory in ''create_node'' "); return -1; } (*create_me)->x = init; (*create_me)->next = 0; return 1; } int main( void ){ struct node *root; create_node(&root, 0); print_all_nodes(root); }
你需要做一些像create_node(&root, 0);
然后在被调用的方法中将其作为**
进行访问。 C没有传递参考概念。 您需要提供地址以在另一个函数中访问它。
这是变量范围的问题。 在第一个示例中,您提供指向节点的指针 ,您可以更改该节点,之后更改将保持不变。 但是, malloc
更改此指针,该指针在作用域(您的函数)结束后将被丢弃。
在第二个示例中,您返回此指针,因此在被丢弃之前复制它。
这将在您给出的示例中对应于此。 3:
void change_i(int* p){ *p = 5; // you can 'change i' p = 5 // but not p (pointer to i), as it is local -> gets discarded after following '}' }
当我给create_node函数指向根节点的指针时,它实际上改变了x和下一个root。
您没有给create_node()
函数(在两个版本中)指向根节点的指针,因为您首先没有根节点。
声明:
struct node *root;
创建类型为struct node *
的变量root
,并使其未初始化。 root
是一个变量,它可以将地址存储在struct node
value(指向struct node
value的指针)的内存中。 但代码不会创建任何struct node
值, root
的值只是垃圾。
接下来,作为调用的结果,函数create_node()
两个版本都在参数create_me
接收root
的垃圾值:
create_node(root, 0);
create_node()
的两个实现的第一件事是忽略它们在create_me
参数中接收的值(无论是否有效),创建struct node
类型的值并将其地址存储在create_me
。
线条:
(*create_me).x = init; (*create_me).next = 0;
将一些值放入新分配的struct node
对象的属性中。
然后函数的第一个版本返回1并忽略存储在create_me
的值。 作为函数参数(函数的局部变量),其值被丢弃并永远丢失。 代码只是创建了一个内存泄漏:一个已分配但无法访问的内存块,因为没有指向它的指针。 不要这样做!
函数的第二个版本返回create_me
的值(即struct node
的新分配值的地址)。 调用代码( root = create_node(root, 0);
)将函数返回的值存储到变量root
(替换用于初始化此变量的垃圾值)。
巨大的成功! create_node()
函数的第二个版本创建一个新的struct node
对象,初始化其属性并返回要存储和/或进一步处理的新对象的地址。 当不再需要该对象时,不要忘记调用free(root)
。