如何正确地将函数返回的const char *转换为C中的const char **?

时间:2010-05-09 04:23:03

标签: c pointers double-pointer const-char libconfig

简而言之,我想这样做:

const char **stringPtr = &getString();

然而,我知道你不能&在右边。所以我坚持这个:

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

7 个答案:

答案 0 :(得分:3)

如果你正在调用需要const char**的函数,你可以这样做:

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

由于在上面的示例中在堆栈上分配了s,如果要从函数中返回const char**,则需要将其放在堆上:

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

HTH

答案 1 :(得分:1)

在您的情况下,

string是本地的,因此获取它的地址是一个坏主意,因为当您离开该方法时,本地的内存可以(并且可能将)重新用于其他目的。通常,在其范围之外使用局部变量的地址不是一个好主意。

你想要达到什么目标?

答案 2 :(得分:1)

不,你不能按照你所描述的方式改变config_setting_lookup_string()。你正在返回一个指向string变量的指针,但只要该函数结束该变量超出范围并被销毁。

但是,您可以很容易地解决您的初始问题。保留config_setting_lookup_string()的定义,并将其称为:

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

答案 3 :(得分:0)

你需要两条线。但是,string是堆栈上的局部变量,一旦超出范围,您可能没有指向getString()返回的数据的指针。

答案 4 :(得分:0)

如果返回stringPtr,您将返回指向局部变量(string)的指针。所以不,你做不到。

你为什么要这样做?这可能会让我们提出更好的建议。

更新: 好的,现在我看到你想要做的事情。你做错了:

value = &string;

如果value用作输出参数,则上述行无效,因为您分配给本地变量

不要让额外的间接水平让你感到困惑。如果您正在编写具有类型T类型的输出参数的函数,则将其写为:

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

现在将T替换为const char*

...
*value = string;
...

现在你不涉及任何临时的局部变量。当然,这就是代码最初编写的方式(并且它的一部分是正确的),所以这对你没有帮助。为了解决你的意图,你应该:

  1. config_setting_lookup_stringassert(value != NULL)
  2. 审核函数的调用者并修复它们以停止传递垃圾。他们应该这样做:

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

  3. 和NOT:

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

答案 5 :(得分:0)

我喜欢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);

答案 6 :(得分:0)

从添加的信息中,您似乎要做的是调用一个想要通过其中一个函数参数返回字符串的函数。在我看来,这样做的最好方法是:

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

这将为堆栈上的const char *分配空间。函数调用将使用要返回的字符串的地址填充指针。如果需要,可以将该指针值传递出函数(与指向指针的指针不同,指针指向堆栈,当函数返回时无效)。 请注意,使用“getString()”初始化fileName可能会泄漏内存,因为返回字符串的指针将被覆盖,并且字符串永远不会被释放。