Как увеличить указатель в C (2d массив) - PullRequest
0 голосов
/ 07 декабря 2018

Мне нужно увеличить указатель на C. Я работаю над функцией, которая вычисляет сумму двух матриц и получает эти матрицы в виде указателей на двумерный массив (double** matrix1 в качестве параметра).Теперь я не знаю, как увеличить этот указатель.

Могу ли я просто использовать *matrix1++ для первого и **matrix1++ для второго указателя?Или как мне увеличить каждый указатель по отдельности?

РЕДАКТИРОВАТЬ: Вот как должна быть объявлена ​​функция:

void matplus (int n, double ** A, double ** B, double ** C)

n - размерность матрицы (пока только квадратичная матрица) A & B - две матрицы, а C - матрица результатов.

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Я собираюсь немного оспорить структуру вопроса: вы не используете правильный тип «двумерного массива» в качестве структуры данных.

В C у вас есть возможностьвызовите вашу функцию с гибкими границами массива.Это позволяет вашим массивам быть прямоугольными , то есть строками одинакового размера, расположенными непрерывно в памяти.Одна простая реализация:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

void sq_matrix_mul( const ptrdiff_t n,
                    const double left[n][n],
                    const double right[n][n],
                    double product[n][n] )
{
    for ( ptrdiff_t i = 0; i < n; ++i )
      for ( ptrdiff_t j = 0; j < n; ++j ) {
        product[i][j] = 0.0;

        for ( ptrdiff_t k = 0; k < n; ++k )
          product[i][j] += left[i][k] * right[k][j];
      } // end for j
}

#define DIMENSION 4

int main(void)
{
  static const double a[DIMENSION][DIMENSION] = {
    { 1, 0, 0, 0 },
    { 0, 2, 0, 0 },
    { 0, 0, 3, 0 },
    { 0, 0, 0, 4 }
  };
  static const double b[DIMENSION][DIMENSION] = {
    { 1, 1, 1, 1 },
    { 1, 1, 1, 1 },
    { 1, 1, 1, 1 },
    { 1, 1, 1, 1 }
  };
  double c[DIMENSION][DIMENSION];

  sq_matrix_mul( DIMENSION, a, b, c );

  for ( ptrdiff_t i = 0; i < DIMENSION; ++i ) {
    fputs( "[ ", stdout );

    for ( ptrdiff_t j = 0; j < DIMENSION; ++j )
      printf( "%f ", c[i][j] );

    fputs( "]\n", stdout );
  }

  return EXIT_SUCCESS;
}

Конечно, есть более сложные алгоритмы умножения массива с лучшим временем выполнения, чем O (N³).

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

Используемая вами структура данных,double**, является рваный массив .Это почти никогда не та структура данных, которую вы действительно хотите (к сожалению, все программисты на C и C ++ сначала узнают о char** argv).Рваные массивы требуют динамического выделения для каждой строки, а не одного для всей матрицы, добавляют поиск указателя для доступа и имеют плохую локальность данных, что делает их намного медленнее.Они также тратят память на все эти указатели.

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

Если вы хотите придерживаться рваного массива, просто используйте прототип функции, который вы сделалидо и держать цикл таким же.Индексы массива, такие как a[i][k], будут работать для рваного или прямоугольного массива.

Мое личное предпочтение состоит в том, чтобы использовать ptrdiff_t (тип, который вы получаете при вычитании указателей) для индексов массива, поскольку они подписаныи не создавайте столько ошибок от тихих переполнений и продвижений типов, сколько делают беззнаковые типы.Они также имеют правильную ширину, не ограниченную 32 битами в 64-битных системах.

Наконец, в C ++ это решение будет недопустимым;Я обычно пишу класс двумерного массива для обеспечения абстракции с нулевой стоимостью.

0 голосов
/ 07 декабря 2018

Я думаю, что если вы хотите вычислить сумму 2 матриц, вы должны увеличить оба указателя следующим образом:

**arrayptr++;

Это потому, что если arrayptr указывает на 2d матрицу, *arrayptr указывает напервый элемент в нем, который является 1d массивом.Для расчета суммы вы хотите выполнить итерацию по каждому отдельному элементу в этих 1d-массивах, которые составляют матрицу.Поэтому используйте **arrayptr для доступа к этим элементам.

Поправьте меня, если я не прав.

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