簡體   English   中英

在另一個函數中的Malloc

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM