[英]Copy a pointer to a struct in a function (linked list)
I want to craete a single linked list without gloabal variables.我想创建一个没有全局变量的单链表。 I initialized the first element with
NULL
and then wanted to copy the first element node
to list_
.我用
NULL
初始化了第一个元素,然后想将第一个元素node
复制到list_
。 It is copied in the function but the side effect isn´t working.它被复制到函数中,但副作用不起作用。 In my main-function the value is still
NULL
.在我的主函数中,该值仍然是
NULL
。 If I return the struct in the add_element()
function all works fine but, is it possible that l
gets the value of node without changing the functions structure and the struct itself?如果我在返回结构
add_element()
函数的所有工作正常,但,有没有可能l
得节点的值不改变功能的结构和结构本身?
#include <stdio.h>
#include <stdlib.h>
struct list {
int value;
struct list *next;
};
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
int add_element(struct list *list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(list_ == NULL)
{
list_ = node;
printf("list_->value = %d\n", list_->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(l,&i);
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); // does not work, l is NULL
return 0;
}
kaylum's comment points you in the right direction. kaylum 的评论为您指明了正确的方向。
When you pass a pointer in C, the pointer's value is copied to the stack, and this copy is the value that the add_element()
function is referring to.当你在 C 中传递一个指针时,指针的值被复制到堆栈中,这个副本就是
add_element()
函数所引用的值。 When you alter the pointer's value, you are modifying the copy placed on the stack, not the original pointer .当您更改指针的值时,您正在修改放置在堆栈上的副本,而不是原始指针。
If you want to alter the original pointer (as if it was passed by reference and not by value) you need to use a double pointer.如果要更改原始指针(就像它是通过引用而不是通过值传递一样),则需要使用双指针。
Try this variant:试试这个变体:
int add_element(struct list **list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(*list_ == NULL) // dereferencing the double pointer will access the original pointer
{
*list_ = node; // this will change the original pointer
printf("(*list_)->value = %d\n", (*list_)->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(&l,&i); // notice you are now passing the address of l instead of its value
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); //should work now
return 0;
}
For starters the function initialize对于初学者,函数初始化
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
does not make great sense.没有多大意义。 You can just write in main
你可以写在 main
struct list *l = NULL;
Or the function initialize
can look like或者函数
initialize
看起来像
inline struct list *initialize(void)
{
return NULL;
}
The function add_element
deals with a copy of the passed list.函数
add_element
处理传递列表的副本。
int add_element(struct list *list_, void *v);
So any changes of the copy do not influence on the original list.因此,副本的任何更改都不会影响原始列表。 Also it is unclear why the second parameter has the type
void *
instead of the type int
.也不清楚为什么第二个参数的类型是
void *
而不是类型int
。
You have to pass the list by reference to the function.您必须通过引用函数来传递列表。
The function can look the following way该函数可以如下所示
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
and called for example like并调用例如
int i = 10;
if ( !add_element( &l, i ) )
{
puts( "Error: not enough memory." );
}
Here is a demonstrative program这是一个演示程序
#include <stdio.h>
#include <stdlib.h>
struct list
{
int value;
struct list *next;
};
static inline struct list * initialize( void )
{
return NULL;
}
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
void output( struct list *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->value );
}
puts( "NULL" );
}
int main(void)
{
struct list *head = initialize();
const int N = 10;
for ( int i = 0; i < N; i++ )
{
add_element( &head, i );
}
output( head );
return 0;
}
Its output is它的输出是
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
Pay attention to that if a new node is appended to the tail of the list then it is better to define the list as a two-sided singly-linked list.注意,如果一个新节点被附加到链表的尾部,那么最好将链表定义为双边单向链表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.