我是C语言的新手,我有一个具有这种结构的函数(这段代码是不可复制的,这是“伪代码”,但我希望它足以解释我的问题):
unsigned** myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
unsigned* cells[nz-1];
unsigned totallength = 0;
unsigned lengths[nz-1];
unsigned** bottomTypes = function1(A, nx, ny, 0);
for(unsigned k=0; k<nz-1; k++){
unsigned** topTypes = function1(A, nx, ny, k+1);
unsigned** cellTypes = function2(bottomTypes, topTypes);
unsigned length
unsigned** goodcells = function3(cellTypes, &length);
cells[k] = malloc(length * sizeof(unsigned));
for(unsigned l=0; l<length; l++){
cells[k][l] = goodcells[0][l] + k;
}
lengths[k] = length;
totallength += length;
bottomTypes = function1(A, nx, ny, k+1); // the same as topTypes
}
unsigned** out = malloc(4 * sizeof(unsigned*));
......
......
return out;
}
如您所见,在循环的末尾,我确实
bottomTypes = function1(A, nx, ny, k+1);
这与前面介绍的topTypes
相同。因此function1(A,nx,ny,k+1)
被调用两次。那是因为我无法在topTypes
中复制bottomTypes
。当我这样做时,代码产生了预期的输出。我没有这样做,为了避免被人怀疑,我试着
**bottomTypes = **topTypes;
或
bottomTypes = malloc((nx-1) * sizeof(unsigned*));
for ( int i = 0; i < nx-1; ++i ){
bottomTypes[i] = malloc((ny-1)*sizeof(unsigned));
memcpy(bottomTypes[i], topTypes[i], ny-1);
}
代码会编译,但我在编译时没有得到预期的结果。
将
topTypes
复制到bottomTypes
的正确方法是什么?我希望这是清楚的。否则不要犹豫,说我不清楚,我会尽量重复,但这并不容易。我也发现了类似的问题,但没有一个能让我解决我的问题。
编辑
下面是一个完整的复制示例。我承认,不是很简单。
#include <stdlib.h> // for malloc
#include <stdio.h> // for printf
// function to create a "three-dimensional array" (I know this is not the correct wording)
// from a given function
double*** fun2array(double f(unsigned,unsigned,unsigned), unsigned nx, unsigned ny, unsigned nz){
double*** out = (double***) malloc(nx * sizeof(double**));
for(unsigned i=0; i<nx; i++){
out[i] = (double**) malloc(ny * sizeof(double*));
for(unsigned j=0; j<ny; j++){
out[i][j] = (double*) malloc(nz * sizeof(double));
for(unsigned k=0; k<nz; k++){
out[i][j][k] = f(i,j,k);
}
}
}
return out;
}
// a three-dimensional array
double fun(unsigned i, unsigned j, unsigned k){
return i+j+k;
}
double*** A = fun2array(fun, 2, 3, 4);
// function to "slice" a 3d-array to a 2D-array (a "matrix")
double** toMatrix(double*** A, unsigned nx, unsigned ny, unsigned k){
double** out = (double**) malloc(nx * sizeof(double*));
for(unsigned i=0; i<nx; i++){
out[i] = (double*) malloc(ny * sizeof(double));
for(unsigned j=0; j<ny; j++){
out[i][j] = A[i][j][k];
}
}
return out;
}
// function to convert double matrix to integer matrix
unsigned** floorMatrix(double** M , unsigned nx, unsigned ny){
unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
out[i][j] = (unsigned) M[i][j];
}
}
return out;
}
// function to sum 2 "matrices"
unsigned** matricialSum(unsigned** M1, unsigned** M2, unsigned nx, unsigned ny){
unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
out[i][j] = M1[i][j] + M2[i][j];
}
}
return out;
}
unsigned myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
unsigned** bottomTypes = floorMatrix(toMatrix(A, nx, ny, 0), nx, ny);
unsigned** cellTypes;
for(unsigned k=0; k<nz-1; k++){
unsigned** topTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny);
cellTypes = matricialSum(bottomTypes, topTypes, nx, ny);
bottomTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny); // the same as topTypes
}
return cellTypes[0][0];
}
int main(){
unsigned result = myfunction(A, 2, 3, 4);
printf("result:%u\n", result);
return 0;
}
第二次编辑
我有一个解决方案,但肯定不是最优的:
unsigned** copyMatrix(unsigned** M, unsigned nx, unsigned ny){
unsigned** MM = malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
MM[i] = malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
MM[i][j] = M[i][j];
}
}
return MM;
}
在示例代码中,我释放了
bottomTypes
,然后unsigned** bottomTypes = copyMatrix(topTypes, nx-1, ny-1);
最佳答案
我终于明白你的问题了,你用**bottomTypes = **topTypes;
代替bottomTypes = topTypes;
。这只是用另一个指针替换指针。
但是,您的代码有很多潜在的问题,比如内存泄漏、使用ThreeStar、强制返回malloc等等。如果您使用C的目的是为了快速,我建议您更改数据结构。malloc()
很贵,除非您想用O(1)
交换矩阵的两行,否则不需要为矩阵的每一行都有一个malloc。
所以:
Do I cast the result of malloc?
如果不需要太多malloc()
你每次掉到topTypes
和bottomTypes
或cellTypes
时都会有内存泄漏,我想只有在你的[mcve]中。
在使用FAM的原始代码中,应该小心使用。
使用无符号而不是size_t
作为索引,如果不使用非常大的矩阵,这不是什么大问题。
你的[mcve]几乎没有修复,到处都是内存泄漏:
#include <stdlib.h> // for malloc
#include <stdio.h> // for printf
// function to create a "three-dimensional array" (I know this is not the
// correct wording)
// from a given function
double ***fun2array(double (*f)(size_t, size_t, size_t), size_t nx, size_t ny,
size_t nz) {
double ***out = malloc(nx * sizeof *out);
for (size_t i = 0; i < nx; i++) {
out[i] = malloc(ny * sizeof *out[i]);
for (size_t j = 0; j < ny; j++) {
out[i][j] = malloc(nz * sizeof *out[i][j]);
for (size_t k = 0; k < nz; k++) {
out[i][j][k] = f(i, j, k);
}
}
}
return out;
}
// a three-dimensional array
double fun(size_t i, size_t j, size_t k) { return i + j + k; }
// function to "slice" a 3d-array to a 2D-array (a "matrix")
double **toMatrix(double ***A, size_t nx, size_t ny, size_t k) {
double **out = malloc(nx * sizeof *out);
for (size_t i = 0; i < nx; i++) {
out[i] = malloc(ny * sizeof *out[i]);
for (size_t j = 0; j < ny; j++) {
out[i][j] = A[i][j][k];
}
}
return out;
}
// function to convert double matrix to integer matrix
unsigned **floorMatrix(double **M, size_t nx, size_t ny) {
unsigned **out = malloc(nx * sizeof *out);
for (size_t i = 0; i < nx; i++) {
out[i] = malloc(ny * sizeof *out[i]);
for (size_t j = 0; j < ny; j++) {
out[i][j] = M[i][j];
}
}
return out;
}
// function to sum 2 "matrices"
unsigned **matricialSum(unsigned **M1, unsigned **M2, size_t nx, size_t ny) {
unsigned **out = malloc(nx * sizeof *out);
for (size_t i = 0; i < nx; i++) {
out[i] = malloc(ny * sizeof *out[i]);
for (size_t j = 0; j < ny; j++) {
out[i][j] = M1[i][j] + M2[i][j];
}
}
return out;
}
unsigned myfunction(double ***A, size_t nx, size_t ny, size_t nz) {
unsigned **bottomTypes = floorMatrix(toMatrix(A, nx, ny, 0), nx, ny);
unsigned **cellTypes = bottomTypes;
for (size_t k = 1; k < nz; k++) {
unsigned **topTypes = floorMatrix(toMatrix(A, nx, ny, k), nx, ny);
cellTypes = matricialSum(bottomTypes, topTypes, nx, ny);
bottomTypes = topTypes;
}
return cellTypes[0][0];
}
int main(void) {
double ***A = fun2array(fun, 2, 3, 4);
unsigned result = myfunction(A, 2, 3, 4);
printf("result:%u\n", result);
}