2016-10-24 3 views
1

Итак, я пытаюсь реализовать связанный стек списков, который принимает аргументы char и добавляет их в список ссылок с его ascii-кодом в качестве значения узлов.Указатель передан для функции не переназначения

Я передаю свой указатель на nstack в свою функцию push и перенаправляю его на new_node, чтобы создать новый верх, но моя функция push не переназначает мой узел nstack - он просто печатает первоначально инициализированный значение nstack. Почему переназначение nstack не назначается?

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

struct list_node { 
    int element; 
    struct list_node * pnext; 
}; 

void push(struct list_node *operators, int e); 

int pop(struct list_node *operators); 


int main(int argc, char *argv[]) { 
    int newvalue = (int)argv[1][0]; 
    struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node)); 

    nstack->element = newvalue; 
    nstack->pnext = NULL; 
    int i; 
     for (i = 2; i < argc; i++) { 
      push(nstack, (int)argv[i][0]); 
     } 
    printf("top: %d\n", nstack->element); 
} 

void push(struct list_node *nstack, int e) { 
    struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node)); 
    new_node->pnext = nstack; 
    new_node->element = e; 
    nstack = new_node; 
} 
+1

C11 черновик стандарта n1570: * 6.5.2.2 Вызовы функций 4 Аргумент может быть выражением любого полного типа объекта. При подготовке к вызову функции вычисляются аргументы и каждому параметру присваивается значение соответствующего аргумента . 93) Функция может изменять значения своих параметров, но эти изменения не могут повлиять на значения аргументов . С другой стороны, можно передать указатель на объект, а функция может изменить значение объекта, на который указывает. * – EOF

+0

'void push (struct list_node * nstack, int e)' может быть 'struct list_node * push (struct list_node * nstack, int e) ', который возвращает указатель, назначаемый вызывающим. Поэтому 'return new_node;' –

+1

Короткая версия: 'nstack = new_node;' в вашей функции push не имеет смысла для вызывающего. Все, что вы меняете, это локальная переменная, а не указатель вызывающего. Или используйте неиспользуемый результат вашей функции, чтобы вернуть новое значение указателя, или передать указатель вызывающего абонента по адресу (как указатель на указатель) и изменить его с помощью де-ссылки. Один из * много * дубликатов этой проблемы [можно найти здесь ** здесь **] (https://stackoverflow.com/questions/19280753/keep-segfaulting-when-trying-to-pass-struct-into-function). – WhozCraig

ответ

1

Потому что вы передаете копию указателя (по значению). Вам нужно что-то вроде этого (указатель на указатель):

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

struct list_node { 
    int element; 
    struct list_node * pnext; 
}; 

void push(struct list_node **operators, int e); 

int pop(struct list_node *operators); 


int main(int argc, char *argv[]) { 
    //int newvalue = (int)argv[1][0]; 
    int newvalue = 1; 
    struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node)); 

    nstack->element = newvalue; 
    nstack->pnext = NULL; 

    int i; 
     for (i = 2; i < 7; i++) { 
      //push(nstack, (int)argv[i][0]); 
      push(&nstack, i); 
     } 
    printf("top: %d\n", nstack->element); 
} 

void push(struct list_node **nstack, int e) { 
    struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node)); 
    new_node->pnext = *nstack; 
    new_node->element = e; 
    *nstack = new_node; 
} 
1

Чтобы расширить правильную точку Тарода. Функция вызывающего абонента делает копию вашего значения указателя и помещает его в стек или в регистр (зависит от компилятора), который затем будет использоваться в вашей функции push. Однако в вашей функции push вы фактически меняете значение в этом регистре или месте стека перед возвратом. Но когда вы возвращаете функцию звонящего, она в принципе отбрасывает эту информацию (ее выталкивает из стека или, опять же, в зависимости от компилятора, использует регистр для чего-то еще). Единственный способ обойти это - передать адрес указателя и почтить его, когда вам нужно написать ему, как показал Тарод.

+0

Спасибо. Я ценю ваш комментарий. У вас есть мой upvote :) – Tarod

 Смежные вопросы

  • Нет связанных вопросов^_^