3

简而言之,我想这样做:

const char **stringPtr = &getString();

但是,我知道您不能 & on rvalues。所以我坚持这个:

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

我可以忍受两条线。我是否在介绍此 hack 的问题?我不应该害怕传递stringPtr出它声明的函数,对吧?

编辑:我很抱歉最初没有包括完整的上下文。我已经承担了暑期项目,即使用 OpenGL 进行图形从头开始用 C 语言构建视频游戏。我正在使用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);
}

分配值的方式意味着,如果您给函数一个 uninitialized 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);
}
4

7 回答 7

3

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

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

由于s在上面的例子中是在堆栈上分配的,如果你想const char**从你的函数中返回 a,你需要把它放在堆上:

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

高温高压

于 2010-05-09T04:53:53.833 回答
1

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

你想达到什么目的?

于 2010-05-09T04:31:49.337 回答
1

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

但是,您可以很容易地解决最初的问题。config_setting_lookup_string()保持原样的定义,并像这样调用它:

const char *fileName = NULL;
config_setting_lookup_string(foo, "bar", &fileName);
于 2010-05-09T06:55:56.373 回答
0

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

于 2010-05-09T04:29:28.967 回答
0

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

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

更新:好的,现在我明白你要做什么了。你这样做是错的:

value = &string;

如果value是作为输出参数,则上述行无法工作,因为您正在分配给局部变量

不要让额外的间接级别让您感到困惑。如果你正在编写一个输出参数为 type 的函数T,你可以这样写:

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

现在替换Tconst char*

...
*value = string;
...

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

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

    常量字符* foo;config_setting_lookup_string(..., &foo);

并不是:

const char** foo;
config_setting_lookup_string(..., foo);
于 2010-05-09T04:29:56.273 回答
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);
于 2010-05-09T07:08:12.167 回答
0

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

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

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

于 2010-05-09T07:32:05.467 回答