【问题标题】:What's the point of having a pointer to pointer to struct as argument?将指向结构的指针作为参数的指针有什么意义?
【发布时间】:2016-12-11 18:27:01
【问题描述】:

我正在学习如何在 Linux 中为 ALSA 编程,有一段代码是这样的:

snd_pcm_t * _soundDevice;

bool Init(const char *name)
{
  int i;
  int err;
  snd_pcm_hw_params_t *hw_params;

  if( name == NULL )
  {
      // Try to open the default device
      err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
  }

如您所见,它首先创建指向结构snd_pmc_t 的指针并将其命名为_soundDevice。然而,代码的其他部分只使用第一个指针:

if ((err = snd_pcm_hw_params_any (_soundDevice, hw_params)) < 0)

我知道指向结构的指针作为参数传递很有帮助,因为将整个结构作为副本传递会很糟糕,而且我也知道这个函数会修改指针指向的结构的内容,但是为什么有人需要一个指向结构指针的指针?

【问题讨论】:

标签: c pointers


【解决方案1】:

为什么有人需要一个指向结构指针的指针?

当您需要以允许函数更改指针指向的内容的方式将指针传递给函数时,这通常会出现。一种惯用的 C 方法是逐个传递指针,从而产生您想知道的第二级间接。

在您的示例中,snd_pcm_open 修改了它的第一个参数(即,使 _soundDevice 指向某个新位置),而 snd_pcm_hw_params_any 没有。

如果snd_pcm_open 采用snd_pcm_t* 而不是snd_pcm_t**,它将无法以传播回调用者的方式重新指向第一个参数。

【讨论】:

  • “修改”是什么意思?例如,给定 struct _soundDevice 的指针,我不能在里面设置东西吗?比如:void (snd_pcm_t * mystruct) { mystruct->something=anything}?
  • @GuerlandoOCs:是的,你可以设置东西“在里面”。你不能做的是修改指针本身
  • 好的,我可以将整个结构指向另一个结构,对吧?不就相当于把一个struct的内容设置成另一个吗?
  • @GuerlandoOCs:不,不一定。您有时希望能够分配一个全新的结构。有时您希望多个指针指向同一个结构,以便对一个结构的更改通过另一个指针自动可见。
【解决方案2】:

在 C 中,参数传递是通过值(或者如果您愿意,也可以通过复制),因此如果您希望函数修改传递的参数作为返回值,您需要传递其地址。

【讨论】:

    【解决方案3】:

    拥有指向指针的指针允许函数修改本地指针。如果您只传递了一个常规指针,则该函数会在堆栈上获取该指针。如果它修改了该值(指针的值,而不是指向的数据的值),则该值会在函数返回时丢失,就像对传递给函数的 int 的更改将丢失一样。如果你改为将指针传递给指针,它可以修改你的指针,该指针在函数返回后仍然存在。

    例如,如果函数正在为该结构分配内存,它可以将指针设置为新分配内存的地址,如果分配失败,则设置为 NULL。在这种情况下,看起来这被用作第二个返回值。它希望返回一个错误代码作为实际返回值,并返回一个指针作为第二个值。

    【讨论】:

      【解决方案4】:

      有时目标不是改变一个对象,而是改变指向它的指针。

      想象一个在多个函数中进行选择的函数“A”

      int A(someType* funcChosen)
      {
           funcChosen = ...; //a pointer to a function
      }
      someType* myFunc;
      int res = A(myFunc);
      

      将修改myFunc。但是您想要一个指向该函数的指针,而不是它的代码 (??)。更好:

      int A(someType** funChosen);
      someType* myFunc;
      int res = A(&myFunc);
      

      【讨论】:

        猜你喜欢
        • 2018-02-09
        • 2021-01-25
        • 1970-01-01
        • 2011-10-24
        • 2013-09-02
        • 1970-01-01
        • 2018-05-16
        • 1970-01-01
        • 2018-04-03
        相关资源
        最近更新 更多