繁体   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