2015-02-05 4 views
2

Я новичок в C. Я знаком с Python, Java, C#. Таким образом, у меня проблемы с указателями.Бесконечная петля и указатели

Я пытаюсь реализовать связанный список в C, используя структуры. На данный момент программа создает член корня, затем добавляет еще один член, чтобы иметь список из 2 связанных членов. Затем он вызывает метод печати, который должен проходить через каждый элемент и печатать их. К сожалению, программа застревает в бесконечном цикле и, похоже, печатает адреса member-> data вместо самих данных.

Как я уже говорил, я знаком с несколькими языками ООП. Эта проблема разочаровывает, потому что простой связанный список - это то, что я должен вытащить за несколько минут. Любая помощь? Код ниже.

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

struct Member{ 
    int data; 
    struct Member *next; 
}; 

struct Member *createMember(int i){ 
    struct Member *new; 
    new = malloc(sizeof(struct Member)); 
    new->data = i; 
    return new; 
} 

void print(struct Member *root){ 
    struct Member *current = root; 
    while(current->next != NULL){ 
     printf("%i, ", current->data); 
     current = current->next; 
    } 
    printf("%i", current->data); 
} 

main(){ 
    struct Member *root; 
    root = createMember(15); 
    root->next = createMember(12); 
    print(root); 
} 
+0

ли он запускал его под отладчиком? – pm100

+3

'createMember' никогда не устанавливает ссылку' next' созданной структуры в NULL. Ваш цикл печати преследует неопределенный указатель от глубины. Если вы собираетесь тестировать NULL, вам лучше убедиться, что в конце концов вы там. – WhozCraig

+0

Я запустил код в gcc и нет бесконечного цикла, и он напечатал как связанные данные 'data'. Но твоя утечка памяти. –

ответ

6

Эта функция:

struct Member *createMember(int i) 
{ 
    struct Member *new; 
    new = malloc(sizeof(struct Member)); 
    new->data = i; 
    return new; 
} 

выделяет пространство и присваивает ваши данные, но никогда не инициализирует next члена. Результатом является то, что элемент, содержащий неопределенные данных, и, следовательно, вызывая неопределенное поведение даже оценить, гораздо меньше разыменования, первый из которых делается здесь:

void print(struct Member *root) 
{ 
    struct Member *current = root; 
    while(current->next != NULL){ // HERE 
     printf("%i, ", current->data); 
     current = current->next; // AND HERE 
    } 
    printf("%i", current->data); 
} 

Для решения этой насущной проблемой изменить функцию распределения инициализировать все пользователей:

struct Member *createMember(int i) 
{ 
    struct Member *new; 
    new = malloc(sizeof(struct Member)); 
    new->data = i; 
    new->next = NULL; // ADDED THIS 
    return new; 
} 

Выход

15, 12 

Остальные проблемы остаются (утечки памяти, поведение print() передается указателем NULL, более педантичная проверка ошибок и т. Д.), Но это наиболее актуально для вашего вопроса.

Удачи.

+0

Итак, это исправляет код. Благодаря тонну. Но как вопрос о том, какой был код, прежде чем я его исправил? Если «member-> next» не «NULL», пока я не назначу его «NULL», каково было до того, как я присвоил ему значение? Только адрес указателя? – mstagg

+1

@mstagg: как сказал WhozCraig, начальное значение 'member-> next' является * неопределенным *; на практике он содержит любой бит-шаблон, который был в последний раз записан в этот раздел памяти. Это может быть или не быть действительным значением указателя (обычно это не так). Обратите внимание, что функция 'calloc' будет инициализировать выделенную память для всех битов 0, что приведет к инициализации' member-> next' в 'NULL'. –

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