C-如何在函数外部更改指针?

时间:2020-06-29 21:43:32

标签: c pointers data-structures

我正在独自研究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)),但这给了我一个分段错误。

为什么第一个示例不能像第二个示例一样工作?

2 个答案:

答案 0 :(得分:0)

在添加,删除或排序链表时,“ head”指针(您的起始指针)中的值可以更改。

要使被调用的函数更改该指针的内容,必须将其地址传递给指针-或-返回该指针的新内容,并将返回的值分配给'head'指针

答案 1 :(得分:0)

此代码

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;
    }
}

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

您需要的是更改函数start中main中定义的指针add_element。在这种情况下,您需要将指针通过引用传递给函数。在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;
}

主要可以写

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