使用指针实现矩阵运算函数:消除二维数组传参强制转换
解决方案:去掉矩阵乘法函数调用的强制类型转换
方案一:使用变长数组(VLA)参数(C99及以上)
这是最优方案,既保留指针操作的效率,又保证类型安全,调用时无需强制转换也不会触发编译器警告。
修改函数声明,将参数改为指向二维数组的指针,注意先声明维度变量再声明数组参数:
void matmult(int m, int n, int k, double (*a)[n], double (*b)[k], double (*c)[k]);
调用时直接传入数组名即可,完全不需要强制转换:
// M、N、K可以是编译期常量或运行时确定的变量 double a[M][N]; double b[N][K]; double c[M][K]; matmult(M, N, K, a, b, c);
函数内部可以用直观的数组下标写法(底层仍是指针运算,效率不变),或者沿用你原来的指针操作逻辑:
void matmult(int m, int n, int k, double (*a)[n], double (*b)[k], double (*c)[k]) { for (int i = 0; i < m; i++) { for (int j = 0; j < k; j++) { c[i][j] = 0.0; // 先初始化结果元素 for (int p = 0; p < n; p++) { // 数组下标写法,等价于你的指针运算逻辑 c[i][j] += a[i][p] * b[p][j]; // 或者沿用原指针写法: // *(c[i] + j) += *(a[i] + p) * *(b[p] + j); } } } }
这个方案的优势在于编译器会自动检查数组维度是否匹配,避免传参错误,同时代码可读性更强。
方案二:兼容C89的void*参数方案
如果需要兼容不支持VLA的旧版C编译器,可以用void*作为参数类型,调用时直接传数组名(数组会退化为指针,void*可以接收任意指针类型),无需强制转换。
函数声明:
void matmult(void *a, void *b, void *c, int m, int n, int k);
调用代码:
double a[M][N]; double b[N][K]; double c[M][K]; matmult(a, b, c, M, N, K); // 无强制转换,无编译器警告
函数内部将void*转换为double*后,沿用你原来的指针运算逻辑:
void matmult(void *a, void *b, void *c, int m, int n, int k) { double *a_ptr = (double*)a; double *b_ptr = (double*)b; double *c_ptr = (double*)c; for (int i = 0; i < m; i++) { for (int j = 0; j < k; j++) { *(c_ptr + i*k + j) = 0.0; for (int p = 0; p < n; p++) { *(c_ptr + i*k + j) += *(a_ptr + i*n + p) * *(b_ptr + p*k + j); } } } }
注意:这个方案会丢失类型检查,如果传入非double类型的指针,编译器不会报错,风险稍高,仅在必须兼容旧标准时使用。
内容的提问来源于stack exchange,提问作者bernhard67
相关产品推荐
相关产品推荐

