[英]Malloc inside another function
我必須從另一個函數中分配一個結構,顯然是使用指針。 我一直在盯着這個問題幾個小時,並嘗試以一百萬種不同的方式來解決它。
這是一些示例代碼(非常簡化):
...
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 * s而不是some_struct s,但是沒有運氣。 我嘗試過:
int allocate(some_struct **arg)
它工作得很好(分配功能也需要更改),但是根據分配,我可能不會更改聲明,而必須是* arg。如果我只需要聲明,那將是最正確的some_struct s .. not some_struct * s。 分配函數的目的是初始化一個結構(some_struct),該結構還包括對其進行分配。
我忘了提一件事。 分配函數中的return 0保留用於某些狀態消息,因此我無法使用此返回地址。
通常,我會從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);
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;
我非常懷疑這是您的老師的想法,但是您可以使用一系列合法的類型轉換作弊。
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指針,反之亦然,而不會丟失。
請注意,這在形式上是未定義的,但是幾乎可以保證一切正常。 盡管要求任何對象指針值都能夠轉換為void*
且無損返回,但該語言中沒有任何東西可以保證some_struct*
可以存儲some_struct**
而不會丟失。 但是它很有可能正常工作。
您的老師別無選擇,只能編寫正式的非法代碼。 除了這種“作弊”之外,我看不到您還有其他選擇。
你不能這樣子。 您不能按值聲明結構,然后按地址更改它。
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;
}
您需要修改結構的指針值。 因此,您需要另一個間接級別,因此必須將指針發送到struct指針。
嗯,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尚未更改。 它仍然具有初始化后的任何隨機數,並將其打印出來。
如果您不更改分配函數的簽名,那么它將永遠無用。 它必須使用指針的地址,以便可以修改該指針的值,或者必須返回一個調用者可以隱藏的指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.