【问题标题】:What does ** mean in C?** 在 C 中是什么意思?
【发布时间】:2015-04-11 03:32:17
【问题描述】:

我有一个示例C 程序我想了解。以下是源代码中的一个函数摘录:

double** Make2DDoubleArray(int arraySizeX, int arraySizeY)
{
  double** theArray;
  theArray = (double**) malloc(arraySizeX*sizeof(double*));
  int i = 0;

  for (i = 0; i < arraySizeX; i++)
    theArray[i] = (double*) malloc(arraySizeY*sizeof(double));

  return theArray;
}

我的问题是** 在返回类型中的意义是什么。我知道* 通常用作pointer。我知道它也可以用来dereference指针。

这让我觉得double** 是一个双精度值,因为它本质上是引用的取消引用。我的想法正确吗?如果没有,有人可以解释一下这个例子中** 的用法吗?

【问题讨论】:

  • 指向指针的指针
  • 首先您需要了解pointer 是什么并停止将其与reference 混为一谈,然后您将知识扩展到pointer to pointer
  • 从右到左读取类型。 double ** 是“指向双精度指针的指针”。你写的,**double,没有意义:“双指向指针。”所以**double 是无效的语法。
  • 也许是因为这个问题可以通过阅读 C 书籍中关于指针的章节来回答。不过我没有投反对票。
  • @S.Morgenstern 所有问题都可以通过阅读正确的书来解决。得出不需要该站点的结论?我认为不是...

标签: c pointers memory reference dereference


【解决方案1】:
some_type*

是指向 some_type 的指针。所以

some_type**

是一个指向 some_type 的指针。

通常用于(模拟)二维数组。

在您的情况下,第一个 malloc 为指向双精度数组的指针保留内存。第二个 malloc 为双精度数组保留内存。通过这种方式,您已经分配了可以像二维数组一样使用的内存。

【讨论】:

    【解决方案2】:

    在这种情况下,double 表示 double 类型的变量。

    double* 表示指向双变量的指针。

    double** 表示指向双变量的指针。

    就您发布的函数而言,它用于创建一种二维双精度数组。也就是说,一个指向双指针数组的指针,每个指针都指向一个指针数组。

    【讨论】:

    • @Jonathan 谢谢。您能否详细说明为什么在本示例的上下文中指向指针的指针有用/必要?
    • @StenSoft:不,指针不是数组。请阅读comp.lang.c FAQ 的第 6 部分。我要求您删除您的评论,因为它可能会误导其他人。数组是“真正的”指针的想法是一种普遍的误解。请不要帮忙传播。
    • @StenSoft:不是真的在 C 中;数组不同于指针(尽管数组会在任何机会隐式转换为指针)。
    • @StenSoft:指针不是数组,数组也不是指针,因为它们密切相关,您可以使用指针作为数组的起始地址。并且double **dptr;double darray[23][17]; 不同,因为dptr[0] 指向/指向一个指针,但darray[0] 一个指针,但不指向一个指针。
    • 二维数组是数组的数组;整个事情在内存中是连续的。指针指向指针可用于实现行为相似的数据结构,每行独立分配,但称其为二维数组会产生误导。
    【解决方案3】:

    作者在 C 中使用一种(不是唯一的)方法来创建二维双精度数组,即创建 Y 个双精度一维数组,以及指向这些的 X 指针的单个数组。这些 Y 数组中的每一个都由 double * 类型的变量访问。然后,他创建了一个指向这些数组中的每一个的指针的一维数组,并将这些指针存储在double ** 类型的数组中,或指针到指针到双精度。 p>

    使用这种方法制作二维数组有几个优点。一,你需要做更少的数学运算来到达一个元素,你甚至可以将这样的数组传递给不需要知道它们的确切尺寸的函数。此外,您可以创建三角形阵列或其他形状,其中子阵列不必全部具有相同的大小。

    唯一的缺点是它们占用了更多内存。

    【讨论】:

    • “更少的数学运算来达到一个元素” - 澄清一下,这意味着使用像 theArray[x_index][y_index] 这样的语法来访问一个元素
    • 另一个可能的缺点是内存不连续,这可能会减慢读取速度,具体取决于您读取元素的顺序。
    • 少数学,当然。但是更多的间接性和严重降低的参考局部性,这两者都更为重要。现在,如果数组应该是锯齿状的,那可能是一个可以接受(也许是不可避免)的决定......
    • 当我说“少数学”时,我的意思是访问这样的数组只需要机器代码中的两次乘以 8 操作,而连续数组需要乘以 8 和乘以内部数组的大小,这可能更昂贵(尽管现在前者的额外内存访问可能消除了这一点)。
    【解决方案4】:

    在您的情况下, this ** 表示指向指针的指针。我想这是不言自明的。 ** 指向一个指针,该指针又指向一个内存位置。如果你想节省内存并且必须声明一个具有 r 行和 c 列的二维数组并且它们是可变的,这很有用。所以接下来就是你要做的

          void create_matrix(int r,int c)
          {
               double ** matrix;
               matrix = (double **)malloc(sizeof(double *)*r);
               for(int i=0;i<r;i++ )
                   matrix[i] = (double *)malloc(sizeof(double)*c);
               /* do operations on matrix */
               return ;
           }
    

    【讨论】:

      【解决方案5】:

      *有多种含义:

      1. 在类型中指定一个指针。
      2. 解引用操作符。
      3. 乘法运算符。

      您的示例仅在用于定义自动变量的类型中使用**
      double**,表示指向double的指针。

      【讨论】:

        【解决方案6】:

        这是一个更通用的答案:spiral rule。对于这个特定的例子:

              +-----------+
              |+--------+ |
              ||  +---+ | |
              ||  ^   | | |
        double** foo; | | |
           ^  |^      | | |
           |  |+------+ | |
           |  +---------+ |
           +--------------+
        

        读作“\”foo\”是一个指向double的指针。”

        在这种情况下,每个指针在语义上都是一个数组,因此这表示一个double 类型的二维数组。

        【讨论】:

          猜你喜欢
          • 2013-03-09
          • 2011-07-07
          • 2016-12-08
          • 2016-04-19
          • 2012-04-25
          • 2011-08-25
          • 2016-04-03
          • 2011-11-26
          • 1970-01-01
          相关资源
          最近更新 更多