2013-06-28 26 views
5

我正在使用GBDK編寫Gameboy ROM,它有一個不穩定的malloc版本,我無法工作。我也無法返回結構中的結構。這讓我試圖返回一個指針,這就是爲什麼我想知道在返回結構指針時是否有避免使用malloc的方法?是否可以在不使用malloc的情況下返回指向結構體的指針?

什麼基本上,我試圖做的是,我希望能夠寫出這樣的事:

create_struct(struct_name, char member_x, char member_y); 

這是我使用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

你的問題是關於如何創建一個對象,而不是如何返回一個指針。 – immibis

回答

4

有多種有效的方式返回一個指針(一種結構或任何類型的對象),但只有這樣,才能返回一個指向一個新的對象未功能之前存在被稱爲是使用malloc,realloc,calloc,aligned_alloc(C11)或一些實現定義的分配函數(例如POSIX系統上的mmap等)。

你可以返回一個有效的指針的其他方式包括:

  1. 指向與static存儲持續時間的對象。只有這樣一個對象的實例存在,所以這通常是一個壞方法。

  2. 作爲參數傳遞給函數的指針,用作存儲結果的地方。這通常是一種好方法,因爲您將獲取存儲的責任轉嫁給了調用者。

  3. 指向從某種全局池獲得的對象的指針。這對於嵌入式系統和低端遊戲設備的遊戲設計來說可能是一個非常好的方法。

+0

我已經嘗試了一些其他的答案,但他們沒有一個似乎與GBDK一起工作。我對你關於全球游泳池的第三個建議感興趣。你有什麼資源可以讓我指點? – MariusGames

+0

如果你已經嘗試了他們,他們「不工作」,我不認爲這意味着你應該嘗試別的。這可能意味着你應該閱讀一些C,並瞭解你做錯了什麼(或者詢問一些具體問題)。無論何時你的代碼沒有做你想做的事,嘗試一種全新的方法並不是一種有效或可靠的編碼方式。 –

+0

謝謝,我知道。歡迎閱讀建議:)我還在學習,但不可能返回結構,因爲GBDK使用C的舊版本。此外,這是一個已知問題,malloc無法正常工作。我會再次回答所有的答案。 – MariusGames

0

剛做類似:

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; 
} 

該結構將需要在其他地方「分配」(可能在堆棧上是你的b est bet)。

0

你可以通過結構類型作爲參數,並有功能初始化:

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

,然後調用它像這樣:

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

但你可能也只是這樣做:

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

請注意,在這種情況下(struct point只佔用2個字節),你可以返回struct point而不是struct point *,(這不應該與大結構來完成)

#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

是否有可能返回一個指向一個結構不使用malloc?

一,從技術上講,是的。你可以讓你的結構static,使其生存函數調用:

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

但我懷疑你真的想這樣做(因爲這有有趣的副作用,對static關鍵詞的含義閱讀起來) 。你有幾種不同的可能性:

二。 C標準庫所採用的方法總是使調用者隱式負責提供結構和管理內存。因此,而不是返回的指針,該函數接受一個指向struct和填充它:

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

III。或者返回結構本身,它不會傷害它嗎?(它甚至可以進行移動優化):

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

所以,選擇你的毒藥。

0

如果無法獲得malloc()固定,那麼您可能只想管理自己的預分配點,並限制可以「創建」的點數。你需要改變你點一點,以便更容易管理:

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; 
}; 

然後,而不是調用由makepoint()返回的結果free(),你應該創建一個新的功能,將它放在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

最簡單的事情就是返回已使用名爲初始化創建的結構,在一個內聯函數這樣做,所以不存在零開銷:

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

然後就可以調用它是這樣的:

struct point foo = makepoint(10, 20); 

不可能更簡單!

相關問題