Указатель на структуру НЕ изменяется при переходе к функции - PullRequest
0 голосов
/ 17 октября 2019

stack.h

 #define MAX_STACK 10
 typedef int STACK_ITEM;
 typedef struct Stack *STACK ;

stack.c

 #include"stack.h"

struct Stack{
    STACK_ITEM contents[MAX_STACK];
    int tos;
};

_Bool create_stack(STACK s){
    s = malloc(sizeof(struct Stack));
    if(s == NULL )
        return 0;
    s->tos = 0;
    return 1;
}

При вызове функции create_stack она не 't влияет на s (указатель на структуру) вообще. Итак, мой вопрос: почему s не меняется , даже если передан указатель, а не значение?

Ответы [ 3 ]

1 голос
/ 17 октября 2019

Чтобы функция C могла изменить аргумент, аргумент должен быть указан как указатель на значение, которое нужно изменить. Таким образом, для простого целочисленного аргумента:

void Inc(int *value) {
    ++(*value);
}

добьется цели, но:

void Inc(int value) {
    ++value;
}

не будет абсолютно ничего делать с любым аргументом, данным в вызове Inc, так какфункция просто получает копию заданного значения.

То же самое относится и к указателю! Ваша функция просто меняет копию указателя, который ей передан. Таким образом, вы должны изменить свою функцию так, чтобы она указывала на указатель:

_Bool create_stack(STACK *s){ // Pointer to a pointer to Stack
    *s = malloc(sizeof(struct Stack)); // Change the value of the STACK object pointed to
    if (*s == NULL )
        return 0;
    (*s)->tos = 0; // And, again, we need to (singly) dereference to 'double' pointer
    return 1;
}

Затем в коде вызова, где у вас изначально есть что-то вроде:

_Bool answer = create_stack(myStackPointer);

, вам понадобитсядобавить адрес вашего указателя:

_Bool answer = create_stack(&myStackPointer);

Не стесняйтесь просить дальнейших разъяснений и / или объяснений.

1 голос
/ 17 октября 2019

Помните, что все параметры передаются по значению в C.

Когда вы передаете указатель в качестве параметра функции, вы можете получить доступ к объекту (или массиву объектов), на который указывает этот указатель.

Вашему create_stack() передается указатель на struct Stack, то есть параметр s. Затем игнорирует исходное значение s и переназначает его. Это разрешено, но обратите внимание, что не изменяет исходный указатель в вызывающей стороне create_stack(), поскольку параметры функции передаются по значению .

Существует дваспособы сделать то, что вы хотите.

Первый способ - передать указатель на указатель:

_Bool create_stack(STACK *s){
    *s = malloc(sizeof(struct Stack));
    if(*s == NULL )
        return 0;
    (*s)->tos = 0;
    return 1;
}

Назовите его, например:

STACK mystack;
_Bool ret;

ret = create_stack(&mystack);
if (!ret) {
    /* error */
}

Второй способэто ничего не передавать и возвращать указатель на выделенный стек:

STACK create_stack(void){
    STACK s = malloc(sizeof(struct Stack));
    if(s != NULL ) {
        s->tos = 0;
    }
    return s;
}

Назовите его, например:

STACK s;

s = create_stack();
if (s == NULL) {
    /* error */
}

Наконец, как точка стиля программирования, не typedefуказатели, как вы сделали. Будет понятнее, если указатель будет явным, например, использовать typedef struct Stack STACK; вместо typedef struct Stack *STACK; и соответственно скорректировать использование, например, заменив STACK s на STACK *s и заменив STACK *s на STACK **s.

1 голос
/ 17 октября 2019

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

Поэтому измените функцию следующим образом:

_Bool create_stack(STACK *s){
    *s = malloc(sizeof(struct Stack));
    if(*s == NULL )
        return 0;
    ( *s )->tos = 0;
    return 1;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...