2013-06-28 6 views
5

Piszę ROM Gameboy używający GBDK, który ma niestabilną wersję malloc, że nie jestem w stanie uzyskać pracy. Nie mogę również zwrócić struktury w strukturze. To sprawia, że ​​próbuję zwrócić wskaźnik, i dlatego zastanawiam się, czy istnieje sposób na uniknięcie używania malloc przy zwracaniu wskaźnika struktury?Czy można zwrócić wskaźnik do struct bez użycia funkcji malloc?

Co mam w zasadzie staramy się robić to, że chcę, aby móc napisać coś takiego:

create_struct(struct_name, char member_x, char member_y); 

Jest to kod mam napisane przy użyciu malloc:

struct point { 
    char member_x; 
    char member_y; 
}; 


struct point *makepoint(char member_x, char member_y) { 
    struct point *temp = malloc(sizeof(struct point)); 

    temp->member_x = member_x; 
    temp->member_y = member_y; 

    return temp; 
}; 
+0

Twoje pytanie dotyczy sposobu tworzenia obiektu, a nie sposobu zwracania wskaźnika. – immibis

Odpowiedz

4

Istnieją różne ważne sposoby zwracają wskaźnik (do struct lub dowolnego typu obiektu), ale to jedyny sposób, aby powrócić wskaźnik do nowy obiekt że nie istniał przed funkcji został wywołany to użycie , , , aligned_alloc (C11) lub niektórych funkcji przydzielania zdefiniowanej przez implementację (np.

Inne sposoby można powrócić ważny wskaźnik obejmują:

  1. wskaźnikiem do obiektu z static okres przechowywania. Tylko raz wystąpienie takiego obiektu istnieje, więc zazwyczaj jest to zła droga.

  2. Wskaźnik, który został przekazany do funkcji jako argument do użycia jako miejsce do przechowywania wyniku. Często może to być dobre podejście, ponieważ przekazujesz rozmówcy odpowiedzialność za uzyskanie miejsca do przechowywania.

  3. Wskaźnik do obiektu uzyskanego z pewnego rodzaju puli globalnej. Może to być bardzo dobre podejście w systemach wbudowanych i projektowaniu gier dla najtańszych urządzeń do gier.

+0

Próbowałem niektóre z innych odpowiedzi, ale żaden z nich nie wydaje się pracować z GBDK. Jestem zainteresowany Twoją trzecią sugestią dotyczącą globalnej puli. Czy masz jakieś zasoby, na które mógłbyś wskazać? – MariusGames

+0

Jeśli je wypróbowałeś i "nie działają", nie sądzę, że powinieneś spróbować czegoś innego. Prawdopodobnie oznacza to, że powinieneś przeczytać trochę, ale więcej na temat C i dowiedzieć się, co robisz źle (lub zadać konkretne pytania). Próba zupełnie nowego podejścia, gdy twój kod nie robi tego, czego chcesz, nie jest wydajnym ani niezawodnym sposobem kodowania. –

+0

Dzięki, wiem. Czytanie sugestii jest mile widziane :) Nadal uczę się, ale nie można zwrócić struktury, ponieważ GBDK używa starej wersji C. Również jest znany problem, że malloc nie działa poprawnie. Przejrzę wszystkie odpowiedzi ponownie. – MariusGames

0

tylko zrób coś takiego:

void makepoint(struct point *dest, char member_x, char member_y) { 
    dest->member_x = member_x; // you had these wrong in your code, by the way 
    dest->member_y = member_y; 
} 

Struktura będzie musiała zostać "przydzielona" w innym miejscu (prawdopodobnie na stosie znajduje się twój b est bet).

0

Mogłeś przejść struct jako parametr i posiada funkcję zainicjować go:

struct point *makepoint(struct point *pt, char x, char y) { 
    pt->x = x; 
    pt->y = y; 
    return pt; 
} 

a następnie nazwać tak:

struct point pt; 
makepoint(&pt, 'a', 'b'); 

ale równie dobrze można po prostu zrobić:

struct point pt = { 'a', 'b' }; 
0

Należy zauważyć, że w tym przypadku (struct point zajmuje tylko 2 bajty) można powrót struct point zamiast struct point * (nie powinno to być zrobione z dużych kodowanym)

#include <stdio.h> 

struct point { 
    char member_x; 
    char member_y; 
}; 

struct point makepoint(char member_x, char member_y) 
{ 
    struct point temp; 

    temp.member_x = member_x; 
    temp.member_y = member_y; 
    return temp; 
} 

int main(void) 
{ 
    struct point t = makepoint('a', 'b'); 

    printf("%c %c\n", t.member_x, t.member_y); 
    return 0; 
} 
2

Czy to możliwe, aby powrócić wskaźnik do struktury bez używania malloc?

I. Technicznie tak. Można dokonać struct static tak, że przetrwa wywołania funkcji:

struct foo *bar() 
{ 
    static struct foo f = { 1, 2, 3 }; 
    return &f; 
} 

Wątpię jednak rzeczywiście chcesz to zrobić (ponieważ ma zabawnych efektów ubocznych, przeczytać o znaczeniu kluczowym static) . Masz kilka różnych możliwości:

II. Podejście, jakie przyjmuje biblioteka standardowa C, zawsze powoduje, że osoba wywołująca pośrednio odpowiada za zapewnienie struktury i zarządzanie pamięcią. Więc zamiast powrocie wskaźnik, funkcja akceptuje wskaźnik do struct i wypełnia go:

void dostuff(struct foo *f) 
{ 
    foo->quirk = 42; 
} 

III. Lub powrót sama struktura, to nie boli, prawda (może to być nawet przenieść zoptymalizowany):

struct foo bar() 
{ 
    struct foo f = { 1, 2, 3 }; 
    return f; 
} 

Więc wybierz truciznę.

0

Jeśli nie można uzyskać stałej malloc(), można po prostu zarządzać własnymi wstępnie przydzielonymi punktami i ograniczyć liczbę punktów, które można "utworzyć". trzeba by zmienić swoje punkty trochę, aby umożliwić łatwiejsze zarządzanie:

union free_point { 
    union free_point *next; 
    struct point data; 
}; 

union free_point free_point_pool[MAX_POINTS]; 
union free_point *free_point_list; 

struct point *makepoint(char member_x, char member_y) { 
    static int i; 
    union free_point *temp; 

    temp = 0; 
    if (i == MAX_POINTS) { 
     if (free_point_list) { 
      temp = free_point_list; 
      free_point_list = temp->next; 
     } 
    } else { 
     temp = free_point_pool + i++; 
    } 

    if (temp) { 
     temp->data.x = x; 
     temp->data.y = y; 
    } 

    return &temp->data; 
}; 

Następnie zamiast dzwonić free() na wynik zwrócony przez makepoint(), należy utworzyć nową funkcję, aby umieścić go na free_point_list.

void unmakepoint (struct point *p) { 
    union free_point *fp = (union free_point *)p; 
    if (fp) { 
     fp->next = free_point_list; 
     free_point_list = fp; 
    } 
} 
0

Najprostszą rzeczą jest to, aby powrócić do struktury, które zostały utworzone za pomocą nazwanych inicjatorów i zrobić w funkcji inline, tak że nie jest zero napowietrznych:

static inline struct point makepoint(char x, char y) { 
    return (struct point) { .x = x, .y = y }; 
} 

Następnie można wywołać to tak:

struct point foo = makepoint(10, 20); 

Nie może być prostsze!