C вопрос относительно указателей в функции - PullRequest
0 голосов
/ 05 августа 2011

У меня есть два вопроса относительно этого кода.

  1. Что означают double*** pdata и int*** pmask? Указатель на указатель на указатель? Почему или когда это необходимо?

  2. int и double - это разные типы, но double* и int* также различны. Можем ли мы оперировать ими без приведения?

Вот код, который я озадачен:

static int makedatamask(int nrows, int ncols, double*** pdata, int*** pmask)
    { int i;
      double** data;
      int** mask;
      data = malloc(nrows*sizeof(double*));
      if(!data) return 0;
      mask = malloc(nrows*sizeof(int*));
      if(!mask)
      { free(data);
        return 0;
      }
      for (i = 0; i < nrows; i++)
      { data[i] = malloc(ncols*sizeof(double));
        if(!data[i]) break;
        mask[i] = malloc(ncols*sizeof(int));
        if(!mask[i])
        { free(data[i]);
          break;
        }
      }
      if (i==nrows) /* break not encountered */
      { *pdata = data;
        *pmask = mask;
        return 1;
      }
      *pdata = NULL;
      *pmask = NULL;
      nrows = i;
      for (i = 0; i < nrows; i++)
      { free(data[i]);
        free(mask[i]);
      }
      free(data);
      free(mask);
      return 0;
    }

Ответы [ 3 ]

1 голос
/ 05 августа 2011

A) *** может быть указателем на массив указателей или двумерным массивом указателей
B) int и double являются разными типами и не могут работать без приведения

1 голос
/ 05 августа 2011

Что означают двойные *** pdata и int *** pmask?Указатель на указатель на указатель?

Да.

[Когда] это необходимо?

Когда, как эта функцияделает, вы хотите вернуть значение указатель-указатель, по указателю.Вы также можете возвращать их по значению, конечно, но эта функция делает это по указателю, потому что она «возвращает» несколько указателей.

int и double - это разные типы, но они типа double * и int * также разные,Можем ли мы оперировать ими без приведения?

Я не уверен, что вы имеете в виду, но вы не можете ожидать, что приведете int* к double* или наоборот;int и double, скорее всего, имеют различное представление в памяти для одних и тех же значений (насколько они могут представлять одинаковые значения) и разных размеров.Вы также нарушили бы правило строгого псевдонима C, сказав

double *p = WHATEVER;
int *q = p;
1 голос
/ 05 августа 2011

Да - это тройные указатели или указатели на указатели на указатели.Иногда они необходимы, но очень боятся.В этом случае вы выделяете два двумерных массива одинакового размера и должны возвращать два значения по ссылке, поэтому необходимы тройные указатели, по крайней мере, пока вы сохраняете текущий дизайн функции.

Да - adouble * и int * - это разные типы;они указывают на разные типы.Вы можете делать соответствующие операции над ними без приведения.Однако, если вы думаете, что можете объединить две параллельные операции в одну, вы, вероятно, ошибаетесь.

Восстановление после ошибки может быть проще, если вы создали несколько подфункций:

static int **alloc_2d_int_array(int nrows, int ncols)
{
    ...
}

static double **alloc_2d_double_array(int nrows, in ncols)
{
    ...
}

Ваша основная функция распределения будет тогда просто вызывать эти два последовательно.Если второй сбой, основная функция выделения вызовет очистку для первого выделенного массива.Коду очистки, вероятно, необходим соответствующий размер, поэтому вы, вероятно, должны иметь:

static void free_2d_double_array(int nrows, double **array)
{
    ...
}

static void free_2d_int_array(int nrows, int **array)
{
    ...
}

Эти функции могут даже отображаться за пределами источника (не static).

Вы также можетерассмотрите возможность использования структуры для описания массивов (строк и столбцов) и указателей на массивы.Это также позволит вам избежать явного обозначения тройного указателя.

struct double_array
{
    int      nrows;
    int      ncols;
    double **array;
};

И т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...