2013-11-11 5 views
2

Я пытаюсь вести реестр сущностей как связанный список с набором функций, которые принимают ссылки на список и изменяют его на месте. Я использовал эту тактику с GLists внутри структур до отличного эффекта, но для этого мне не нужна структура контейнера. То, что я пытаюсь сделать это:Pass GList по ссылке

// Creates a new entity and appends it to the global entity index. 
// Returns ID of the newly created entity, not a pointer to it. 
int anne_entity_create(char entity_name[], char entity_type[], GList *Entities) { 

    ANNE_ENTITY *newEntity = malloc(sizeof(ANNE_ENTITY)); 
    ANNE_ENTITY_RECORD *newEntityRecord = malloc(sizeof(ANNE_ENTITY_RECORD)); 

    newEntity->id = anne_entity_get_next_id(Entities); 
    sprintf(newEntity->name, "%s", entity_name); 
    sprintf(newEntityRecord->name, "%s", entity_name); 

    newEntityRecord->entity = newEntity; 

    Entities = g_list_append(Entities, newEntityRecord); 

    printf("Index length: %i\n", g_list_length(Entities)); 

    return newEntity->id; 
} 

//Entity system setup 
GList* Entities = NULL; 
printf("Entity ID: %i\n", anne_entity_create("UNO", "PC", Entities)); 
printf("Entity ID: %i\n", anne_entity_create("DOS", "PC", Entities)); 
printf("Index length: %i\n", g_list_length(Entities)); 

g_list_length() внутри anne_entity_create() возвращает 1, в то время как та же функция выполняется за пределами возвращает 0. Очевидно, что GList копируется как это передается anne_entity_create(), но я m в убытке за причину - и передать его & ссылка не должна быть необходимой, поскольку (насколько я понимаю) создание GList с синтаксисом приводит к указателю в любом случае.

Я уверен, что я неправильно понимаю то, что я делаю совершенно, но я уже несколько часов проделывал это.

ответ

2

Вы передаете один указатель на свою функцию, что означает, что вы можете изменить то, на что указывает указатель, в данном случае NULL, и вы работаете с локальным указателем (с областью действия вашей функции anne_entity_create), что указывает на NULL, то к этому указателю вы «прикрепляете» свой список, что делает его доступным только локально.

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

GList *Entities = NULL; 
anne_entity_create("UNO", "PC", &Entities) //Inside your function pass *Entities to append 

// Creates a new entity and appends it to the global entity index. 
// Returns ID of the newly created entity, not a pointer to it. 
int anne_entity_create(char entity_name[], char entity_type[], GList **Entities) { 

    ANNE_ENTITY *newEntity = malloc(sizeof(ANNE_ENTITY)); 
    ANNE_ENTITY_RECORD *newEntityRecord = malloc(sizeof(ANNE_ENTITY_RECORD)); 

    newEntity->id = anne_entity_get_next_id(*Entities); 
    sprintf(newEntity->name, "%s", entity_name); 
    sprintf(newEntityRecord->name, "%s", entity_name); 

    newEntityRecord->entity = newEntity; 

    *Entities = g_list_append(*Entities, newEntityRecord); 

    printf("Index length: %i\n", g_list_length(*Entities)); 

    return newEntity->id; 
} 
+0

'GList ** Сущности; * Сущности = NULL; 'segfaults. Заглядывая в нее, но я только понимаю, что вы предлагаете. –

+1

Принцип этого ответа правильный, но приведенный код действительно будет segfault. Я пошел дальше и отредактировал его ;-) – ptomato

+0

Да, я испортил, это segfaults, потому что двойной указатель не инициализирован, как изменен картофель, вы должны передать ссылку указателя или выделить двойной указатель, но решение, предоставляемое картофелем лучше. – Sinn

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