Почему я должен возвращать указатель, когда я работаю с динамическим типом данных? (то есть стек, список, очередь, динамический массив) - PullRequest
0 голосов
/ 10 января 2019

При использовании функции pop и push я должен вернуть указатель, иначе стек переменных не изменится. Кто-нибудь знает почему?

#include <stdio.h>
#include <stdlib.h>

//Defining stack element
typedef struct element
{
    int num;              //Content of the element
    struct element *next; //Pointer to the next element
}element;

element *push(element *s, int x); //Insert x elements in the stack
void print(element *s);           //Prints the stack's elements
element *pop(element *s);         //Removes the stack's top element

int main()
{
    element *stack = NULL; //Pointer to the stack's top element
    int x;

    printf("Insert the number of elements: ");
    scanf("%d", &x);

    stack = push(stack, x);
    print(stack);

    stack = pop(stack);
    print(stack);

    return 0;
}

element *push(element *s, int x)
{
    element *newElement;

    for(; x > 0; x--)
    {
        newElement = (element*)malloc(sizeof(element));

        printf("Number: ");
        scanf("%d", &newElement->num);

        newElement->next = s;
        s = newElement;
    }

    return s;
}

void print(element *s)
{
    element *through = s;

    printf("Your stack:\n");

    while(through != NULL)
    {
        printf("%d\t", through->num);
        through = through->next;
    }
    printf("\n");
}

element *pop(element *s)
{
    element *elementDeleted = s;
    s = elementDeleted->next;

    printf("Element deleted: %d\n", elementDeleted->num);

    free(elementDeleted);
    elementDeleted = NULL;

    return s;
}

Я просто ожидал изменить стек указателей в функциях, поэтому я ожидал, что функции будут недействительными. Но на самом деле, если я не возвращаю указатель, переменная стека сохраняет свое начальное значение (в данном случае NULL).

1 Ответ

0 голосов
/ 10 января 2019

Вам необходимо использовать двойной указатель в аргументах вашей функции:

// Add a new value to the top of the stack
void push(element **s, const int x);
// Print the stack
void print(const element *s);
// Try removing the top element of the stack and returning it
int pop(element **s);

Затем вы вызываете push и pop со ссылкой на указатель стека:

push(&stack, x);
pop(&stack);

Затем, если вы хотите изменить указатель на стек, вы разыменовываете s один раз: *s = newElement, но если вы хотите получить значение верхнего элемента, вы разыменовываете его дважды: const int num = (*s)->num;.

Причина, по которой это необходимо сделать, заключается в том, что когда вы передаете указатель на стек в функцию, эта функция получает копию указателя. Этот новый указатель ссылается на тот же стек, поэтому изменение значений в стеке будет работать, но изменение самого указателя ничего не будет делать вне функции.

Если вместо этого вы используете указатель на указатель на ваш стек, то вы разрешаете модифицировать этот второй указатель, поскольку только указатель верхнего уровня является копией.

...