2010-04-08 48 views
2

我必須從另一個函數中分配一個結構,顯然是使用指針。 我一直在盯着這個問題幾個小時,並試圖用一百萬種不同的方式來解決它。Malloc裏面另一個函數

這是一些示例代碼(很簡單):

... 
some_struct s; 
printf("Before: %d\n", &s); 
allocate(&s); 
printf("After: %d\n", &s); 
... 

/* The allocation function */ 
int allocate(some_struct *arg) { 

arg = malloc(sizeof(some_struct)); 
printf("In function: %d\n", &arg); 

return 0; 
} 

這確實給我同樣的地址之前和分配呼叫後:

Before: -1079752900 
In function: -1079752928 
After: -1079752900 

我知道這可能是因爲它使函數中的一個副本,但我不知道如何實際處理作爲參數的指針。我嘗試了定義some_struct *而不是some_struct,但沒有運氣。我試着用:

int allocate(some_struct **arg) 

它工作得很好(需以及改變分配功能),而是根據分配我可能不會改變的聲明,它必須是* ARG。而這將是最正確的,如果我只需要聲明some_struct s ..不是some_struct * s。 分配函數的目的是初始化一個struct(一個some_struct),它也包括分配它。

還有一件事我忘了提。分配函數中的返回0保留給一些狀態消息,因此我不能使用這個返回地址。

+1

'allocate'函數的真正目的是什麼? – Earlz 2010-04-08 15:50:30

+1

如果你必須傳遞一個'* some_struct',並在要分配的函數內分配內存,那麼分配是不可能的。你能否發表更多的作業細節,大概你應該學習什麼? – 2010-04-08 15:59:56

+0

哦,當你發佈更多的細節時,這裏要做的正確的事情就是編輯你的問題來包含它們。你在這裏似乎是新手,可能不知道禮儀。 – 2010-04-08 16:14:16

回答

1

我很懷疑這是你的老師有什麼介意,但是您可以使用一系列合法類型轉換來作弊。

int allocate(some_struct *arg) 
    /* we're actually going to pass in a some_struct ** instead. 
     Our caller knows this, and allocate knows this. */ 
    { 
     void *intermediate = arg; /* strip away type information */ 
     some_struct **real_deal = intermediate; /* the real type */ 
     *real_deal = malloc(sizeof *real_deal); /* store malloc's return in the 
               object pointed to by real_deal */ 
     return *real_deal != 0; /* return something more useful than always 0 */ 
    } 

然後呼叫方不相同:

{ 
     some_struct *s; 
     void *address_of_s = &s; 
     int success = allocate(address_of_s); 
     /* what malloc returned should now be what s points to */ 
     /* check whether success is non-zero before trying to use it */ 
    } 

這依賴於在C規則說,任何指向對象的指針可以隱式轉換爲空指針,反之亦然,沒有失利。

請注意,形式上這是未定義的,但它是所有,但肯定工作。儘管任何對象指針值都需要能夠轉換爲void*,並且沒有丟失,但語言中沒有任何內容保證some_struct*可以存儲some_struct**而不會丟失。但它很有可能工作得很好。

你的老師給你別無選擇,只能寫正式的非法代碼。除了這樣的「作弊」之外,我沒有看到你有任何其他選擇。

+0

謝謝。這似乎工作,但代碼不漂亮。是的,我覺得它也很奇怪。該函數也必須返回0,因爲我忘了提及。 但我記得pthreads ..據他所知,他們的工作就像這樣。 你初始化這樣的一些屬性: pthread_attr_t attr; pthread_attr_init(&attr); ,然後你用的是作爲參數調用在pthread_create。 這init的分配pthread_attr_t結構。 – Casper 2010-04-08 16:34:17

+0

我有一種揮之不去的感覺,規範分配得到某處出現亂碼,無論是在老師的結束或卡斯帕的我會認真仔細地檢查一下這個任務的意圖,然後再打開。 – 2010-04-08 19:21:55

+0

是的,我有點覺得我誤解了任務..這個問題只是其中的一部分 是必須的是一個some_struct * arg參數,也許我應該從函數內部分配數據,但是函數沒有目的。嗯..這很奇怪。 – Casper 2010-04-09 09:06:16

0

你不能這樣做。你不能通過值聲明一個結構體,然後通過地址來改變它。

+1

我有時希望'&foo = ...'是有效的語法。 :P – Earlz 2010-04-08 16:00:10

0
some_struct *s; 
printf("Before: %d\n", s"); 
allocate(&s); 
printf("After: %d\n", s"); 
... 

/* The allocation function */ 
int allocate(some_struct **arg) { 

*arg = malloc(sizeof(some_struct)); 
printf("In function: %d\n", *arg"); 

return 0; 
} 

您需要修改結構的指向值。所以你需要另一個間接級別,因此你必須發送一個指向結構指針的指針。

+0

他指出他不允許這樣做。 – 2010-04-08 15:55:09

+0

@Jason,那麼這是不可能的。 – Earlz 2010-04-08 15:59:37

+0

@Earlz:我認爲David有他的教授正在尋找的答案嗎? – 2010-04-08 16:03:03

4

通常情況下,我會從allocate返回指針:

void * allocate() 
{ 
    void * retval = malloc(sizeof(some_struct)); 
    /* initialize *retval */ 
    return retval; 
} 

如果你想在一個參數返回它,你有一個指針傳遞給該參數。由於這是一個指向some_struct,你有一個指針傳遞給一個指針:

void allocate (some_struct ** ret) 
{ 
    *ret = malloc(sizeof(some_struct)); 
    /* initialization of **ret */ 
    return; 
} 

被稱爲

some_struct *s; 
allocate(&s); 
0

好,C採用傳遞的價值,這意味着函數獲得副本的參數,並且對這些副本所做的任何更改都不會影響調用方中的原始副本。

/* The allocation function */ 
int allocate(some_struct *arg) { 

arg = malloc(sizeof(some_struct)); 
printf("In function: %d\n", &arg"); 

return 0; 
} 

在這裏你傳遞你的some_struct的地址。然後丟棄該地址,並將其替換爲malloc返回的內容。然後你返回,並且malloc的返回值永遠丟失,並且你泄露了內存。你的some_struct沒有改變。它仍然有任何它被初始化的隨機數,你打印出來的。

如果您不能更改分配函數的簽名,它永遠不會有用。它必須接受一個指針的地址,以便它可以修改該指針的值,或者它必須返回一個指向你的調用者可以放開的指針。

1
int func(some_struct *arg) { 
    arg = malloc(sizeof(some_struct)); 
    ... 
} 

在這裏,您只需將malloc的結果分配給本地arg變量。指針通過C中的值傳遞,指針的副本傳遞給函數。你不能以這種方式改變調用者的指針。請記住指針的不同以及它指向的內容。

你有多種選擇:

返回從函數指針:

some_struct *func(void) { 
    arg = malloc(sizeof(some_struct)); 
    ... 
    return arg; 
} 
... 
some_struct *a = func(); 

分配在調用者的結構:

int func(some_struct *arg) { 
    ... 
    arg->something = foo; 

} 
... 
some_struct a; 
func(&a); 

或動態分配它

some_struct *a = malloc(sizeof *a); 
func(a); 

使用指針的調用者:

int func(some_struct **arg) { 
    *arg = malloc(sizeof **arg); 

} 
... 
some_struct *a; 
func(&a); 

使用全局變量(醜..)

some_struct *global; 
int func(void) { 
    global = malloc(sizeof *global); 

} 
... 
some_struct *a; 
func(); 
a = global; 
相關問題