2016-07-04 6 views
0

次のコードでは、Cでポインタで実現される基本的な整数リンクリストを見ることができます。 新しいint-リストの前にあるval。 私はこれらの2つの機能は同等だと考えましたが、出力が示すとおり、そうではありません。C:リンクリスト - 関数 "insert first"が期待どおりに動作しない

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

typedef struct _IntlistElem* Intlist; 
typedef struct _IntlistElem {int val; Intlist next;} IntlistElem; 

Intlist insertfirst(int val, Intlist list) { 
    Intlist new = malloc(sizeof(IntlistElem)); 
    new->val = val; 
    new->next = list; 

    return new; 
} 

Intlist insertfirstAlternative(int val, Intlist list) { 
    IntlistElem new = {val, list}; 
    Intlist head = &new; 

    return head; 
} 

void print(Intlist l){ 
    while (l!=NULL){ 
     printf("%d\n", l->val); 
     l = l->next; 
    } 
printf("_____\n"); 
} 

int main(){ 
    Intlist ls = NULL; 
    ls = insertfirst(2, ls); 
    ls = insertfirst(1, ls); 
    print(ls); 

    Intlist lsAlt = NULL; 
    lsAlt = insertfirstAlternative(2, lsAlt); 
    lsAlt = insertfirstAlternative(1, lsAlt); 
    print(lsAlt); 

    return 0; 
} 

出力:

1 
2 
_____ 
1 
1 
... 

私の質問は以下のとおりです。
1. はなぜ印刷機能が終了していませんか? (代替関数を呼び出した後)
2. これらの2つの「insertfirst」関数は、私が期待したものと同等ではないのはなぜですか?
これらの機能の違いは何ですか?

私はあなたの答えを楽しみにしています。 :)

+0

デバッガを使用して、行単位でステップ実行する際に、コードフローと現在の変数値を検査する方法を緊急に学習する必要があります。 –

+1

'Intlist head = &new;': 'new'はローカル自動変数です。有効範囲外です。 – BLUEPIXY

+0

このコードは警告フラグとともにコンパイルされません(gccは-Wall -Werror -Wextraです)。私はあなたが次回それらを使用することをお勧めします。 – qleguennec

答えて

1

あなたの関数insertfirstAlternativeheadへのポインタを返します。その変数の存続期間は、関数から戻って終了します。したがって、無効なポインタ値を返します。

ポインターの値は、それが指すオブジェクトが有効期限の終わりに達すると不確定になります。

何かが起こる可能性があります。

2回目にこの関数を呼び出すと、nextポインタが同じオブジェクトを指しているので、最初の関数と同じアドレスに2番目のheadが作成されます。したがって、無限ループ。

+0

まずは、ありがとうございます。しかし、 "insertfirst"が終了した後、割り当てられたIntlistElem変数の "new"ポイントも生き続ける可能性があります。 – CptCook

+0

それは生きていない。効率上の理由から、メモリはクリアされず、そのアドレスから(ダングリングポインターを介して)種類の作業が読み取られます。しかし、これはちょうど偶然です。その間に他の機能を呼び出すと、メモリが再利用され上書きされる可能性があります。 –

+0

ありがとうございます。つまり、リンクされたリストを「安全」にする方法はありません。 – CptCook

関連する問題