Недопустимые типы 'float [int]' для индекса массива при попытке получить длину столбца 2d массива - PullRequest
0 голосов
/ 23 мая 2019

При попытке умножить 2 матрицы

void Multiply(float* A, float* B, float* C)
{
    int m = sizeof(A) / sizeof(A[0]);
    int p = sizeof(A[0]) / sizeof(A[0][0]);
    int n = sizeof(B) / sizeof(B[0]);

    int i, j, k;
    for (i = 0;i < m;i++)
        for (j = 0;j < n;j++)
        {
            C[n*i + j] = 0;
            for (k = 0;k < p;k++)
                C[n*i + j] = C[n*i + j] + A[p*i + k] * B[n*k + j];
        }
}

я получаю ошибку invalid types 'float[int]' for array subscript в этой строке

int p = sizeof(A[0]) / sizeof(A[0][0]);

Что я делаю не так?

1 Ответ

2 голосов
/ 23 мая 2019

В подпрограмме, которая вызывает Multiply, A может быть определено как float A[X][Y];.Однако Multiply получает только указатель, а не массив.Кроме того, Multiply не получает информации о размерах исходных массивов, поэтому они не могут быть рассчитаны в подпрограмме.Они должны быть переданы вызывающей стороной.

Когда в выражении используется массив, включая аргумент функции, но исключая операнд sizeof или унарный & (или строковый литерал, используемый для инициализации массива), он автоматически преобразуется в указатель на свой первый элемент.

Если A является массивом X массивов Y float, то первый элемент A являетсямассив Y float.Поэтому, когда A используется в качестве аргумента функции, он автоматически преобразуется в тип float (*)[Y].Это отличается от объявления параметра, которое float *.Указатель на массив float не совместим с указателем на float, и ваш компилятор должен предупредить вас об этом.

Если вы все же компилируете программу с игнорируемыми предупреждениями или приведением кпереопределите типы, тогда Multiply имеет только float * для A.У него нет информации о размере массива или о том, что это массив массивов.Затем в выражении sizeof(A) / sizeof(A[0]) (в котором скобки не нужны), sizeof(A) - это размер указателя на float, потому что A - это указатель на float и sizeof (A [0]) is the size of a float , because A [0] is a float (as it must be since A in Multiply is a float * `).

Параметр B имеет ту же проблему с размеромрасчет.В Multiply, B является только указателем на float, размер sizeof(B) / sizeof(B[0]) вычисляет только размер указателя, деленный на размер float.Он не предоставляет размер исходного массива.

Как ни странно, ваш код использует A как двумерный массив в A[0][0], так и одномерный массив в A[p*i + k].Вы должны выбрать один из них.

Если ваш компилятор поддерживает массивы переменной длины, тогда вы можете объявить Multiply как:

void Multiply(int m, int p, int n, float (*A)[p], float (*B)[n], float (*C)[n])

Затем вы можете использовать A[i][k], B[k][j]и C[i][j] в рутине.В вызывающей подпрограмме вы бы записали исходные массивы в качестве аргументов, например, Multiply(X, Y, Z, A, B, C), где X, Y и Z - необходимые измерения.

Альтернативой является передачамассивы как указатели на float вместо указателей на массивы переменной длины:

void Multiply(int m, int p, int n, float *A, float *B, float *C)

Тогда вы будете использовать A[p*i + k], как показано в текущем коде.В вызывающей подпрограмме вы будете передавать указатели на [0][0] элементы массивов: Multiply(X, Y, Z, &A[0][0], &B[0][0], &C[0][0]).

Педантически, это может иметь проблемы с алиасами и указателями, так как результирующий код обращается к элементам float с использованием индексарасчеты вне номинальных массивов.Обычно он поддерживается в компиляторах, но вы должны проверить.

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