首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是C中结构赋值的有效用法吗?

这是C中结构赋值的有效用法吗?
EN

Code Review用户
提问于 2012-02-26 05:56:29
回答 1查看 376关注 0票数 4

问:请评论C中结构和结构分配操作的使用情况。

我正在使用BLAS和LAPACK将MATLAB程序转换成C来支持线性代数。MATLAB代码使用单元格数组。我创建了一个矩阵数据类型和一个单元数据类型。

头文件/实现的一部分:

代码语言:javascript
复制
#define ASSERT(c,m) 
#define PREC double

#define ZEROS(r,c) (zeros(r,c))
#define ONES(r,c) (ones(r,c))
#define EYE(r,c) (eye(r,c))
#define ALLOCM(r,c) (alloc_matrix(r,c))
#define PRINTM(M) (print_matrix(M))
#define FREEM(M) (free_matrix(M))

#define ALLOCC(r,c) (alloc_cell(r,c))
#define GETMC(C,r,c) (get_matrix_from_cell(C,r,c))
#define SETMC(C,r,c,M) (set_matrix_in_cell(C,r,c,M))
#define FREEC(C) (free_cell(C))

/* Matrix */
typedef struct {
  PREC * array;
  int rows; // The number of rows in the matrix
  int cols; // The number of columns in the matrix
}Matrix;


/* Cell of Matrices */
typedef struct {
  Matrix * array; // Cell array of matrices stored in row major form
  int rows;  // Number of rows in Cell array
  int cols;  // Number of cols in Cell array
}Cell;


/* Matrix utility functions */
Matrix  alloc_matrix(int rows, int cols);
Matrix  zeros(int rows, int cols);
Matrix  ones(int rows, int cols);
Matrix  eye(int rows, int cols);
Matrix  corrcov(Matrix matrix);
void print_matrix(Matrix matrix);
void free_matrix(Matrix  matrix);

/* Cell array utility functions */
Cell alloc_cell(int rows, int cols);
INLINE Matrix get_matrix_from_cell(Cell cell, int row, int col);
INLINE void set_matrix_in_cell(Cell  cell, int row, int col, Matrix matrix);
void free_cell(Cell cell); 

// Implementation
Matrix 
alloc_matrix(int rows, int cols){

  Matrix matrix;

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);

  matrix.array = (PREC *) malloc(sizeof(PREC) * rows * cols);

  ASSERT(matrix.array != NULL, FATAL_NO_MEMORY);

  matrix.rows = rows;

  matrix.cols = cols;

  return matrix;
}



Matrix 
zeros(int rows, int cols){

  int i;

  int size;

  Matrix matrix;

  matrix = alloc_matrix(rows, cols);

  for(i = 0, size = rows * cols; i < size ; i++){
    matrix.array[i] = 0.0;
  } 

  return matrix;
}



void
print_matrix(Matrix matrix){

  int i;  

  int j;

  int k;

  int rows = matrix.rows;

  int cols = matrix.cols;

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);  

  ASSERT(matrix.array != NULL, FATAL_NULL_POINTER);

  printf("\n Rows: %d, Cols: %d\n", rows, cols);

  for(i = 0 ; i < rows; i++){
    for(j = 0, k = i * cols; j < cols; j++){
      printf("%8.6f  ", matrix.array[ k + j ]);
    }
    printf("\n");
  }  

}


void 
free_matrix(Matrix matrix){

  ASSERT(matrix.array != NULL, FATAL_NULL_POINTER);

  free(matrix.array);

  matrix.array = NULL; 

}


Cell 
alloc_cell(int rows, int cols){

  Cell cell;

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);

  cell.array = (Matrix *) malloc(sizeof(Matrix) * rows * cols);

  ASSERT(cell.array != NULL, FATAL_NO_MEMORY);

  cell.rows = rows;

  cell.cols = cols;

  return cell; 
}



void 
free_cell(Cell cell){

  int i;

  int size;

  int rows = cell.rows;

  int cols = cell.cols;

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);

  ASSERT(cell.array != NULL, FATAL_NULL_POINTER);

  for( i = 0, size = rows * cols; i < size; i++){
    free_matrix(cell.array[i]);                       
  }

  free(cell.array);

}


INLINE Matrix 
get_matrix_from_cell(Cell cell, int row, int col){

  Matrix matrix;

  int rows = cell.rows;

  int cols = cell.cols;

  ASSERT(cell.array != NULL, FATAL_NULL_POINTER);

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);

  ASSERT(row >= 0 && row < rows, FATAL_INDEX_OUT_OF_BOUNDS);

  ASSERT(col >= 0 && col < cols, FATAL_INDEX_OUT_OF_BOUNDS);

  matrix = cell.array[(row * cols) + col];

  return matrix; 
}



INLINE void
set_matrix_in_cell(Cell cell, int row, int col, Matrix matrix){

  int rows = cell.rows;

  int cols = cell.cols;

  ASSERT(cell.array != NULL, FATAL_NULL_POINTER);

  ASSERT(rows > 0 && cols > 0, FATAL_NEGATIVE_DIMENSIONS);

  ASSERT(row >= 0 && row < rows, FATAL_INDEX_OUT_OF_BOUNDS);

  ASSERT(col >= 0 && col < cols, FATAL_INDEX_OUT_OF_BOUNDS);

  cell.array[(row * cols) + col] = matrix;

}

注意,我不返回分配矩阵类型对象或单元格类型对象的函数的指针。我返回一个普通的矩阵或Cell对象,但是我在这些函数中分配数组(矩阵的PREC类型和单元格的矩阵类型--其中PREC是双倍或浮动的)。

这很方便,因为:

  1. struct赋值是C中的一个有效操作(我知道动态分配的数据不是重复的,只是对它的引用)
  2. 要获得矩阵中的元素,我可以使用dot语法而不是->语法(而且,如果我使用点语法- matrix.array我 vs matrix.array->数组,则可能只需要取消引用一次)。
  3. 大多数矩阵对象和单元对象(不包括动态分配的内存)都在堆栈上,并且在函数退出时自动释放,我觉得,跟踪不再使用的对象并在必要时释放它们比较容易。

我分析了一个使用此接口的示例程序。

示例程序:

代码语言:javascript
复制
#include "matutil.h"

int main(){

  Matrix mz;

  Cell cell;

  mz = ZEROS(3,3);

  PRINTM(mz);

  cell = ALLOCC(1,1);

  SETMC(cell,0,0,mz);  

  PRINTM(GETMC(cell, 0 , 0));

  FREEC(cell);

  return 0;
}

这个问题是矩阵对象(Matrix ),我从它开始,没有显式初始化它的数组字段,所以,瓦伦报告。

代码语言:javascript
复制
==17433== Conditional jump or move depends on uninitialised value(s)

这是问题吗?在进行这个设计之前,我是否应该意识到有什么缺陷呢?

谢谢。

EN

回答 1

Code Review用户

回答已采纳

发布于 2012-02-27 10:45:58

关于

关于你的英勇的问题

我不认为英勇警告是关于矩阵中未初始化的字段。您的zeros函数进行初始化,对吗?我用以下代码测试了自己:

代码语言:javascript
复制
Matrix zeros(int rows, int cols) {
    Matrix tmp;
    int i;

    tmp.rows = rows;
    tmp.cols = cols;
    tmp.array = malloc(sizeof(float) * rows * cols);

    for(i = 0; i < rows * cols; i++)
        tmp.array[i] = 0;

    return tmp;
}

我没有英勇的警告。共享一段代码(实际上产生了val差事警告)会有帮助。

其他备注

  • 如果您想要自动释放内存并复制分配的内存,C++将提供帮助。
  • 不过,我不明白你对点语法的看法。您只是添加一个层次的嵌套,这并不意味着您将使用"*“或"->”更少。
  • matrix->array[i]是错误的,因为->[]都取消了指针的引用:这不会编译
  • 为什么不使用PREC**指针呢?它可能更容易使用,并将避免错误。
  • 你想让你的MATLAB代码更快吗?矩阵运算可能非常快使用matlab。如果代码的另一部分比较慢,请考虑使用MEX-档案
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/9439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档