2016-10-24 18 views
1

char引数をとり、リンクリストにノードの値としてasciiコードを追加するリンクリストスタックを実装しようとしています。ポインタが関数に代入されないように渡されました

私はpush関数にnstackポインタを渡し、新しいtopを作成するために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;'はプッシュ機能では呼び出し側にとって無意味です。変更しているのは、呼び出し側のポインタではなくローカル変数だけです。関数の使用されない結果を利用して新しいポインタ値を返すか、呼び出し側のポインタをアドレス(ポインタへのポインタ)として渡して、逆参照によって変更します。この問題の*複数の重複の1つ* [ここに** **見つけられる**](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

Tarodの正しい点を拡大します。呼び出し元関数が行っていることは、ポインタ値のコピーを取得し、それをプッシュ関数で使用されるスタックまたはレジスタ(コンパイラ依存)に置くことです。ただし、プッシュ関数内では、実際にこのレジスタまたはスタック位置の値を変更してから戻します。しかし、呼び出し元関数を返すと、基本的にこの情報が破棄されます(スタックがポップされたか、またはコンパイラによっては別のもののためにレジスタが使用されます)。この周りの唯一の方法は、Tarodが示しているように、ポインタのアドレスを渡してそれに書き込む必要があるときにこれを尊重することです。

+0

ありがとうございます。私はあなたのコメントに感謝します。あなたは私のupvoteを持っている:) – Tarod

関連する問題