2015-04-16 4 views
1

В настоящее время я начинаю работать с c и allegro5. Я хочу поместить мой код инициализации в метод init(), но я пытаюсь вернуть указатели на ALLEGRO_EVENT_QUEUE и ALLEGRO_DISPLAY. Хотя указатели инициализируются в функции, они по-прежнему остаются NULL; Я думал, что значения, назначенные указателям, останутся в конце текущей области, потому что базовое значение будет изменено, но адрес памяти останется прежним. Вот мой код:C возвращающие структуры через указатель

#include <stdio.h> 
#include <allegro5/allegro.h> 

void init(ALLEGRO_DISPLAY *display_ptr, ALLEGRO_EVENT_QUEUE *queue_ptr) { 
    al_init(); 
    al_install_keyboard(); 
    display_ptr = al_create_display(640, 480); 
    queue_ptr = al_create_event_queue(); 
    al_register_event_source(queue_ptr, al_get_display_event_source(display_ptr)); 

    al_clear_to_color(al_map_rgb(0,0,0)); 

    al_flip_display(); 
} 

int main(int argc, char **argv){ 

    ALLEGRO_DISPLAY *display = NULL; 
    ALLEGRO_EVENT_QUEUE *event_queue = NULL; 

    init(display, event_queue); 
    printf("%d\n", display == NULL); //prints out 1 
    printf("%d\n", event_queue == NULL); //prints out 1 

    //Further code 

    return 0; 
} 

Любой намек или помощь очень ценится.

ответ

3

Вам необходимо передать адрес указателя.

Попробуйте, как это

void init(ALLEGRO_DISPLAY **display_ptr, ALLEGRO_EVENT_QUEUE **queue_ptr) { 
    al_init(); 
    al_install_keyboard(); 
    *display_ptr = al_create_display(640, 480); 
    *queue_ptr = al_create_event_queue(); 
    /* I assume you are guaranteed to not recieve `NULL's or why don't you check ? */ 
    al_register_event_source(*queue_ptr, al_get_display_event_source(*display_ptr)); 

    al_clear_to_color(al_map_rgb(0,0,0)); 

    al_flip_display(); 
} 

и

init(&display, &event_queue); 

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

Передавая адрес указателю, вы можете изменить адрес, хранящийся в указателе.

Если вы хотите проверить, что я говорю true, попробуйте напечатать адрес указателей в каждой функции, и вы увидите, что они разные.

+0

Yay! Оно работает! Большое спасибо. –

+1

Просто примите ответ, когда сможете. –

1

Параметры вызываются по значению, то есть в вашем случае адрес указателя не возвращается.

Чтобы обойти, что вам нужно передать указатели на указатели, как это:

#include <stdio.h> 
#include <allegro5/allegro.h> 

void init(ALLEGRO_DISPLAY **display_ptr, ALLEGRO_EVENT_QUEUE **queue_ptr) { 
    al_init(); 
    al_install_keyboard(); 
    *display_ptr = al_create_display(640, 480); 
    *queue_ptr = al_create_event_queue(); 
    al_register_event_source(*queue_ptr, al_get_display_event_source(*display_ptr)); 

    al_clear_to_color(al_map_rgb(0,0,0)); 

    al_flip_display(); 
} 

int main(int argc, char **argv){ 

    ALLEGRO_DISPLAY *display = NULL; 
    ALLEGRO_EVENT_QUEUE *event_queue = NULL; 

    init(&display, &event_queue); 
    printf("%d\n", display == NULL); //prints out 1 
    printf("%d\n", event_queue == NULL); //prints out 1 

    //Further code 

    return 0; 
} 
+1

Не работать, это правильный способ сделать это. –

+0

Это спорно. Обходным путем является отсутствие вызова по ссылке, например, например. C++. – Meixner

+1

Вы имеете в виду, что c уступает, потому что это не делает вашу жизнь более трудной, пройдя по ссылке? По-моему, переход по ссылке запутан, потому что вы можете забыть, что переданная переменная будет изменена, поэтому переход по ссылке - одна из уродливых вещей в C++, и она когда-то стоила мне больших денег. –