В подпрограмме, которая вызывает 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
с использованием индексарасчеты вне номинальных массивов.Обычно он поддерживается в компиляторах, но вы должны проверить.