簡體   English   中英

如何正確地將函數返回的const char *轉換為C中的const char **?

[英]How do I properly turn a const char* returned from a function into a const char** in C?

簡而言之,我想這樣做:

const char **stringPtr = &getString();

但是,據我所知,你不能和rvalues一樣。 所以我堅持這個:

const char *string = getString();
const char **stringPtr = &string;

我可以忍受兩條線。 我是否介紹了這個黑客的問題? 我不應該害怕將stringPtr傳遞給它聲明的函數,對嗎?

編輯:我最初沒有包括完整的上下文。 我參與了夏季項目,使用OpenGL進行圖形處理,從頭開始構建視頻游戲。 我正在使用libconfig從文本文件中讀取配置數據。

從配置文件中查找特定字符串的便捷函數之一如下所示:

int config_setting_lookup_string(const config_setting_t *setting,
                                 const char *name, const char **value)
{
  config_setting_t *member = config_setting_get_member(setting, name);
  if(! member)
    return(CONFIG_FALSE);

  if(config_setting_type(member) != CONFIG_TYPE_STRING)
    return(CONFIG_FALSE);


  *value = config_setting_get_string(member);
  return(CONFIG_TRUE);
}

分配值的方式意味着如果您為函數提供未初始化的value ,它會嘗試解除未定義的垃圾,這幾乎總是會導致我的段錯誤。 我目前解決此問題的方法是首先將value初始化為另一個指針,如下所示:

const char *dummyPtr;
const char **fileName = &dummyPtr;
config_setting_lookup_string(foo, "bar", fileName);

所以我試圖找出重寫函數最后一部分的最佳方法,這樣我就不必執行這個兩步初始化。 我以為改變后的函數看起來像這樣:

int config_setting_lookup_string(const config_setting_t *setting,
                                 const char *name, const char **value)
{
  config_setting_t *member = config_setting_get_member(setting, name);
  if(! member)
    return(CONFIG_FALSE);

  if(config_setting_type(member) != CONFIG_TYPE_STRING)
    return(CONFIG_FALSE);

  const char *string = config_setting_get_string(member);
  value = &string;
  return(CONFIG_TRUE);
}

如果你正在調用一個需要const char**const char** ,你可以這樣做:

const char *s = getString();
myFunction(&s);

由於在上面的例子中s被分配在堆棧上,如果你想從函數中返回一個const char** ,你需要把它放在堆上:

const char **sp = malloc(sizeof(const char *));
*sp = getString();
return sp;

HTH

在你的情況下, string是本地的,因此獲取它的地址是一個壞主意,因為當你離開方法時,本地的內存可以(並且可能將)重新用於其他目的。 通常,在其范圍之外使用局部變量的地址並不是一個好主意。

你想要實現什么目標?

不,您不能以您描述的方式更改config_setting_lookup_string() 您將返回一個指向string變量的指針,但只要該函數結束該變量超出范圍並被銷毀。

但是,您可以非常輕松地修復初始問題。 保留config_setting_lookup_string()的定義,並按如下方式調用它:

const char *fileName = NULL;
config_setting_lookup_string(foo, "bar", &fileName);

你需要兩條線。 但是,string是堆棧上的局部變量,一旦超出范圍,您可能沒有指向getString()返回的數據的指針。

如果返回stringPtr ,則將返回指向局部變量( string )的指針。 所以不,你做不到。

你為什么要這樣做? 這可能會讓我們提出更好的建議。

更新:好的,現在我看到你正在嘗試做什么。 你這樣做是錯的:

value = &string;

如果value表示輸出參數,則上述行無法工作,因為您要分配給局部變量

不要讓額外的間接水平讓你感到困惑。 如果您正在編寫具有類型T的輸出參數的函數,則將其寫為:

void foo(T* value)
{
    *value = GetT();
}

現在用const char*替換T

...
*value = string;
...

現在你不涉及任何臨時的局部變量。 當然,這就是代碼最初編寫的方式(並且它的一部分是正確的),所以這對你沒有幫助。 為了滿足您的意圖,您應該:

  1. make config_setting_lookup_string do assert(value != NULL)
  2. 審核函數的調用者並修復它們以停止傳遞垃圾。 他們應該這樣做:

    const char * foo; config_setting_lookup_string(...,&foo);

並不是:

const char** foo;
config_setting_lookup_string(..., foo);

我喜歡nornagon和caf的解決方案,

const char *fileName;
config_setting_lookup_string(foo, "bar", &fileName);

但如果您可以更改config_setting_lookup_string您也可以這樣做:

int config_setting_lookup_string(..., const char *&value)
{
  ...
  const char *string = config_setting_get_string(member);
  value = string;
  ...
}

const char *fileName;
config_setting_lookup_string(foo, "bar", fileName);

從添加的信息中,您似乎要做的是調用一個想要通過其中一個函數參數返回字符串的函數。 在我看來,這樣做的最好方法是:

const char* fileName;
config_setting_lookup_string(..., &fileName);
(...)
return fileName;

這將為堆棧上的const char *分配空間。 函數調用將使用要返回的字符串的地址填充指針。 如果需要,可以將該指針值傳遞出函數(與指向指針的指針不同,指針指向堆棧,當函數返回時無效)。 請注意,使用“getString()”初始化fileName可能會泄漏內存,因為返回字符串的指針將被覆蓋,並且字符串永遠不會被釋放。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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