2016-10-24 26 views
1

所以我試圖實現一個鏈接列表堆棧,它接受char參數,並將它們添加到鏈接列表中,並將它作爲ascii代碼作爲節點的值。指針傳遞到函數不重新分配

我將我的nstack指針傳入我的推送函數,並將其重新分配給new_node以創建新的頂層,但我的推送函數似乎沒有重新分配我的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-intofunction )。 – 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

拓展Tarod的正確點。調用者函數正在做的是獲取指針值的一個副本,並將其放到堆棧或寄存器中(依賴於編譯器),然後將其用於您的推送函數中。然而,在你的push函數中,你實際上是在返回之前改變這個寄存器或棧位置的值。但是當你返回調用者函數時基本上丟棄了這個信息(它從棧中彈出 - 或者依賴於編譯器,再使用寄存器來做其他事情)。解決這個問題的唯一方法是傳遞指針的地址,並在Tarod顯示的時候需要寫入該地址時遵循該地址。

+0

謝謝。感謝您的評論。你有我的讚賞:) – Tarod