【问题标题】:C - How to alter a pointer outside a function?C - 如何更改函数外部的指针?
【发布时间】:2020-10-20 03:33:21
【问题描述】:

我正在自己研究 C 中的数据结构,我正在尝试实现一个链表,但我不明白如何在添加新值时更改起始指针。这是我的实际代码:

#include <stdlib.h>

typedef struct node {
    int value;
    struct node *next;
};

struct node *transverse_list(struct node *start) {
    struct node *current_node;
    struct node *last;

    current_node -> next = start;

    while(current_node -> next != NULL) {
        printf("Current value: %d\n", current_node -> value);
        current_node = current_node -> next;
    }

    last = current_node;

    return last;
}

void add_element(int value, struct node *start) {
    struct node *new_node, *ptr_new_node;

    new_node = (struct node *) malloc(sizeof(struct node));
    ptr_new_node = (struct node *) malloc(sizeof(struct node));

    if(start == NULL) {
        printf("start: %d\n", start);
        new_node -> value = value;
        new_node -> next = NULL;
        start = new_node;
        printf("start: %d\n", start);
        printf("Pointer value: %d\n", start -> value);
    } else {
        struct node *last;
        last = transverse_list(start);
        new_node -> value = value;
        ptr_new_node = NULL;
        new_node -> next = ptr_new_node;
    }
}

int main() {
    struct node *start = NULL;

    add_element(2, start);
    add_element(3, start);
    add_element(5, start);
    add_element(7, start);
    add_element(11, start);
    add_element(13, start);

    transverse_list(start);

    return 0;
}

哪些打印:

start: 0
start: 7084208  
Pointer value: 2
start: 0        
start: 7084240  
Pointer value: 3
start: 0        
start: 7084272
Pointer value: 5
start: 0
start: 7084304
Pointer value: 7
start: 0
start: 7083968
Pointer value: 11
start: 0
start: 7084000
Pointer value: 13

我之前为另一个练习编写了这段代码,它的 sum() 函数改变了 main 函数中指针的值。

void sum(int*, int*, int*);

int main() {
    int num1, num2;
    int *total;

    num1 = 10;
    num2 = 15;

    sum(&num1, &num2, &total);
    printf("Sum: %d\n", total);

    return 0;
}

void sum(int *a, int *b, int *t) {
    *t = *a + *b;
}

哪些打印:

Sum: 25

我试图将起始指针传递给 add_element 函数(例如:add_element(2, &start)),但它给了我一个分段错误。

为什么第一个例子不像第二个例子那样工作?

【问题讨论】:

  • 您需要使用指针来启动,add_element(2, &amp;start); 以更新到启动值。次要备注不要强制转换 malloc 结果
  • 你永远不会改变 start in main。如果要在调用者中修改变量,则必须传递变量的地址。也就是说,你应该调用add_element(2, &amp;start)并将add_element的原型更改为struct node **
  • 要么像add_element(2, &amp;start);那样传递start的地址,要么使用像start = add_element(2, start);这样的返回值。相应地更改add_element()。您的选择。
  • 旁注:为了获得最佳风格,从不这样做(例如):new_node -&gt; value总是这样做:@ 987654335@
  • 你能提供一个更具体的问题吗?这可能有助于更好地了解您对代码输出的期望。

标签: c pointers data-structures


【解决方案1】:

在添加、删除或排序链表时,“头”指针(您的起始指针)中的值可能会发生变化。

要让被调用函数更改该指针的内容,必须将指针的地址传递给它——或者——返回该指针的新内容,并将返回的值分配给“头”指针

【讨论】:

    【解决方案2】:

    这段代码

    void sum(int*, int*, int*);
    
    int main() {
        int num1, num2;
        int *total;
    
        num1 = 10;
        num2 = 15;
    
        sum(&num1, &num2, &total);
        printf("Sum: %d\n", total);
    
        return 0;
    }
    
    void sum(int *a, int *b, int *t) {
        *t = *a + *b;
    }
    

    不正确,因为在这个陈述中

    *t = *a + *b;
    

    您正在尝试在此语句中分配一个带有整数的指针而不进行强制转换

    printf("Sum: %d\n", total);
    

    您在输出指针时使用了错误的转换说明符 %d

    这些功能

    struct node *transverse_list(struct node *start) {
        struct node *current_node;
        struct node *last;
    
        current_node -> next = start;
    
        while(current_node -> next != NULL) {
            printf("Current value: %d\n", current_node -> value);
            current_node = current_node -> next;
        }
    
        last = current_node;
    
        return last;
    }
    
    void add_element(int value, struct node *start) {
        struct node *new_node, *ptr_new_node;
    
        new_node = (struct node *) malloc(sizeof(struct node));
        ptr_new_node = (struct node *) malloc(sizeof(struct node));
    
        if(start == NULL) {
            printf("start: %d\n", start);
            new_node -> value = value;
            new_node -> next = NULL;
            start = new_node;
            printf("start: %d\n", start);
            printf("Pointer value: %d\n", start -> value);
        } else {
            struct node *last;
            last = transverse_list(start);
            new_node -> value = value;
            ptr_new_node = NULL;
            new_node -> next = ptr_new_node;
        }
    }
    

    没有意义,调用未定义的行为并产生内存泄漏。

    您需要更改函数add_element 中main 中定义的指针start。在这种情况下,您需要通过引用函数来传递指针。在 C 中,通过引用传递意味着通过指针间接传递对象。

    函数add_element可以通过以下方式声明和定义

    int add_element( struct node **start, int value ) 
    {
        struct node *new_node = malloc( sizeof( struct node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->value = value;
            new_node->next  = NULL;
    
            while( *start != NULL ) start = &( *start )->next;
    
            *start = new_node;
        }
    
        return success;
    }
    

    据我了解,函数transverse_list 用于输出列表。可以通过以下方式声明和定义

    FILE * transverse_list( struct node *start, FILE *fp ) 
    {
        for ( struct node *current = start; current != NULL; current = current->next )
        {
            fprintf( fp, "%d -> ", current->value );
        }
    
        fputs( "null", fp );
    
        return fp;
    }
    

    在 main 你可以写

    struct node *start = NULL;
    
    add_element( &start, 2 );
    add_element( &start, 3 );
    add_element( &start, 5 );
    add_element( &start, 7 );
    add_element( &start, 11 );
    add_element( &start, 13 );
    
    transverse_list( start, stdout );
    

    注意这个typedef

    typedef struct node {
        int value;
        struct node *next;
    };
    

    没有多大意义,因为它没有为struct node 类型引入别名。相反,你可以写例如

    typedef struct node {
        int value;
        struct node *next;
    } node;
    

    或者你可以只声明结构

    struct node {
        int value;
        struct node *next;
    };
    

    这是一个演示程序

    #include <stdio.h>
    #include <stdlib.h>
    
    struct node 
    {
        int value;
        struct node *next;
    };
    
    int add_element( struct node **start, int value ) 
    {
        struct node *new_node = malloc( sizeof( struct node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->value = value;
            new_node->next  = NULL;
    
            while( *start != NULL ) start = &( *start )->next;
    
            *start = new_node;
        }
    
        return success;
    }
    
    FILE * transverse_list( struct node *start, FILE *fp ) 
    {
        for ( struct node *current = start; current != NULL; current = current->next )
        {
            fprintf( fp, "%d -> ", current->value );
        }
    
        fputs( "null", fp );
    
        return fp;
    }
    
    int main(void) 
    {
        struct node *start = NULL;
    
        add_element( &start, 2 );
        add_element( &start, 3 );
        add_element( &start, 5 );
        add_element( &start, 7 );
        add_element( &start, 11 );
        add_element( &start, 13 );
    
        transverse_list( start, stdout );
        
        return 0;
    }
    

    程序输出是

    2 -> 3 -> 5 -> 7 -> 11 -> 13 -> null
    

    【讨论】:

    • 非常感谢!您不仅提出了主要问题,还澄清了代码中的其他内容。感谢您和其他回答的人,现在我对代码中发生的事情以及如何处理指针有了更好的理解。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 2012-03-13
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    相关资源
    最近更新 更多