Ошибка при умножении матричного вектора — недопустимые операнды на двоичный * (имеют ‘double *’ и ‘double *’)

#c #matrix #vector #multiplication

#c #матрица #вектор #умножение

Вопрос:

Я пытаюсь умножить большую и случайную матрицу (NxN) и случайный вектор (N), используя указатели. Почему я получаю сообщение об ошибке типа «недопустимые операнды на двоичные * (имеют ‘double *’ и ‘double *’)»? Ошибка, похоже, в ptr3 [i] [j] = ptr3 [i] ptr1 [i] * ptr2 [k]; но я не могу понять, почему это не работает. Я новичок в C, поэтому я все еще не очень хорошо понимаю указатели.

 int main ()
{
    time_t t;
    double **ptr1, **ptr2, **ptr3;
    int i, j, k;
    int N = 500;
    ptr1 = (double **) malloc (sizeof (double *) * N);
    ptr2 = (double **) malloc (sizeof (double *) * N);
    ptr3 = (double **) malloc (sizeof (double *) * N);

    for (i = 0; i < N; i  )
        ptr1[i] = (double *) malloc (sizeof (double) * N);
    for (i = 0; i < N; i  )
        ptr2[i] = (double *) malloc (sizeof (double) * N);
    for (i = 0; i < N; i  )
        ptr3[i] = (double *) malloc (sizeof (double) * N);

    for (i = 0; i < N; i  ) {
        for (j = 0; j < N; j  ) {
            ptr1[i][j] = rand ();
        }
    }
for (i = 0; i < N; i  ) {
            *ptr2[i] = rand ();
    }
    t = clock();

    for (i = 0; i < N; i  ) {

            ptr3[i] = 0;
            for (k = 0; k < N; k  )
                ptr3[i] = ptr3[i]   ptr1[i][k] * ptr2[k];

    }

   t = clock() - t;
    double time_taken = ((double)t)/CLOCKS_PER_SEC;
    printf("Tempo:  %f segundos n", time_taken);

 printf ("n");
    return (0);
} ```
 

Комментарии:

1. Как говорится в сообщении: in ptr3[i][j] = ptr3[i] ptr1[i] * ptr2[k]; — это ptr3[i][j] double значение, но остальные три являются указателями, и их добавление / умножение не имеет смысла.

2. Также обратите внимание, что вы создали ptr2 2D-массив, подобный ptr1 and ptr3 , а не 1D-массив, упомянутый в описании и инициализированный в цикле.

3. Похоже, что опубликованный код изменяется без комментариев.

4. Это похоже на вопрос «зыбучий песок». Пожалуйста, скопируйте / вставьте ваш фактический код и оставьте его, чтобы комментарии и ответы оставались актуальными.

Ответ №1:

Что говорит компилятор , так это то , что в операторе ptr3[i] = ptr3[i] ptr1[i] * ptr2[k]; бит , который говорит ptr1[i] * ptr2[k] , пытается переключиться * между двумя выражениями , которые имеют тип double* . Другими словами, вам не разрешается умножать два указателя вместе. Чтобы сделать это правильно, вам нужно снова выполнить разыменование ( [i] и [k] уже разыменовывают double** на a double* ). Чтобы заставить это скомпилироваться, это утверждение должно быть (я добавил круглые скобки для ясности — на самом деле они не нужны):

 *ptr3[i] = (*ptr3[i])   (*ptr1[i]) * (*ptr2[k]);
 

Это должно привести вас к компиляции, но следующая проблема, с которой вы столкнетесь, — ошибка сегментации. На две строки выше места, где вы выполняете умножение, у вас есть это:

 ptr3[i] = 0;
 

Это присваивается ptr3[i] нулевому указателю, который такой же, как 0 в C (другие языки имеют другое имя этого значения: null , None , и т.д.). Я думаю, вы хотели сделать вот что:

 *ptr3[i] = 0;
 

Кроме того, поскольку N это известное фиксированное значение, вы можете отказаться от всего malloc этого, просто сказав:

 const int N = 500;
double ptr1[N][N];
double ptr2[N][N];
// ... and so on ...
 

Это объявление ptr1 в виде массива вместо указателя, который идентичен указателю с точки зрения шаблонов доступа к памяти, но отличается несколькими способами. В зависимости от того, что вы пытаетесь изучить, отказ от работы с динамической памятью (с использованием malloc и free ) может пока избавить вас от небольшой головной боли.