- 主题:请教两个二级指针的问题
我写了一段计算矩阵的转置矩阵的程序,运行虽然没有报错,但是我觉得我程序里是不是有两个错误?
(1)验证了if( AT == NULL )之后,没必要再验证if( AT[i] == NULL )吧?属于多此一举;
(2)定义**XT后缺少生成2行5列的全零矩阵的步骤。程序这次虽然没有出错,但容易出现内存地址被占用的情况?
有没有大牛给指点两句?谢谢
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
double ** Mat_tra(double **A,int Row_A,int Line_A)
//子函数:计算矩阵A的转置矩阵AT,
{
double **AT;//创建A的转置矩阵
int i,j;
AT=(double**)calloc(Line_A,sizeof(double*)); //
if( AT == NULL )
{
printf( "内存分配失败\n" );
return 0;
}
else
{};
for(i=0;i<Line_A;i++)
{
AT[i]=(double*)calloc(Row_A,sizeof(double));//
if( AT[i] == NULL )
{
printf( "内存分配失败\n" );
return 0;
}
else
{};
for(j=0;j<Row_A;j++)
{
AT[i][j]=A[j][i];
}
}
return AT;
}
void Print_mat(double **A,int Row_A,int Line_A)
//子函数:打印数组
{
int i,j;
for(i=0;i<Row_A;i++)//
{
for(j=0;j<Line_A;j++)
{
printf("%5.3g ",A[i][j]);
if(Line_A!=1)
//如果 Line_A==1,则会出现除以0的情况,子函数会不报错就退出;
{
if ((j!=0)&(j%(Line_A-1)==0) )
printf("\n");
}
else
{
printf("\n");
}
}
}
printf("\n");
}
int main()
{
double **X,**XT;
int i,j;
int Row_X=2;
int Line_X=5;
int Row_XT=5;
int Line_XT=2;
X=(double**)calloc(Row_X,sizeof(double*));
if( X == NULL )
{
printf( "内存分配失败\n" );
return 0;
}
else
{};
for(i=0;i<Row_X;i++)//
{
X[i]=(double*)calloc(Line_X,sizeof(double));
if( X[i] == NULL )
{
printf( "内存分配失败\n" );
return 0;
}
else
{};
for(j=0;j<Line_X;j++)
{
X[i][j]=i+j*j;
}
}
XT=Mat_tra(X,Row_X,Line_X);
//将X转置并复制到指针XT标识的内存中
Print_mat(X,Row_X,Line_X);
Print_mat(XT,Row_XT,Line_XT);
return 0;
}
--
FROM 111.193.233.*
没仔细看代码
我想说的是另外一个角度:
二维动态数组,也是可以用一维的数组来实现的,不需要进行二次的内存分配。
也就是分配一段内存,直接在逻辑视图上视为二维数组(视为三维、N维也是一样的)。
const int M = 3;
const int N = 5;
int* p = (int*)malloc(sizeof(int) * M * N);
for (int i = 0; i < (M * N); ++i) p[i] = i;
int(*a)[M][N] = (int(*)[M][N])p;
for (int row = 0; row < M; ++row) {
for (int col = 0; col < N; ++col) {
printf("%d ", (*a)[row][col]);
}
printf("\n");
}
free(p);
--
FROM 221.218.160.*
(1)if( AT == NULL )和if( AT[i] == NULL )都需要验证,不是多此一举,根本就是两回事。当然实际执行中==NULL很少,因为分配内存基本都能成功。
(2)使用以前分配就可以。
结论是代码没有错误,但代码质量很差。
【 在 sqsl 的大作中提到: 】
: 我写了一段计算矩阵的转置矩阵的程序,运行虽然没有报错,但是我觉得我程序里是不是有两个错误?
: (1)验证了if( AT == NULL )之后,没必要再验证if( AT[i] == NULL )吧?属于多此一举;
: (2)定义**XT后缺少生成2行5列的全零矩阵的步骤。程序这次虽然没有出错,但容易出现内存地址被占用的情况?
: ...................
--
FROM 120.245.114.*
好的,谢谢,学习了
【 在 z16166 的大作中提到: 】
: 没仔细看代码
: 我想说的是另外一个角度:
: 二维动态数组,也是可以用一维的数组来实现的,不需要进行二次的内存分配。
: ...................
--
FROM 111.193.233.*
好的,谢谢
子函数内分配内存有可能不知道主函数的内存规划,容易越界是吧?
【 在 ylh0315 的大作中提到: 】
: 都是必须的。
: 建议,不要在函数内分配内存。内存在函数外分配,用毕销毁。
: 最好是谁分配的谁负责销毁。
: ...................
--
FROM 111.193.233.*
好的,谢谢
代码质量差除了前面版友说的子函数内部分部内存外,还有其他什么毛病?我是新手,
想改进代码质量
【 在 longsword 的大作中提到: 】
: (1)if( AT == NULL )和if( AT[i] == NULL )都需要验证,不是多此一举,根本就是两回事。当然实际执行中==NULL很少,因为分配内存基本都能成功。
: (2)使用以前分配就可以。
: 结论是代码没有错误,但代码质量很差。
: ...................
--
FROM 111.193.233.*
建议用一重指针,在main里面把输入、输出的缓冲区都分配好作为参数传给子函数。
函数的参数,指针都加上 restrict,方便编译器优化。
不要用 // 格式的注释,一律用 /* */
应该表扬的是所有的if都写了else
【 在 sqsl 的大作中提到: 】
: 我写了一段计算矩阵的转置矩阵的程序,运行虽然没有报错,但是我觉得我程序里是不是有两个错误?
: (1)验证了if( AT == NULL )之后,没必要再验证if( AT[i] == NULL )吧?属于多此一举;
: (2)定义**XT后缺少生成2行5列的全零矩阵的步骤。程序这次虽然没有出错,但容易出现内存地址被占用的情况?
: ...................
--
FROM 59.41.161.*
一、你这个代码其实是有内存泄漏的
下面这种“遇到失败就返回”的模式称为early return。
if (xxx == NULL) {
return;
}
在每个early return之前,是需要释放掉前面所分配的任何内存(或者资源)的。
Mat_tra()里的第二个early return以及更后面的return,没有释放掉前面那个calloc()分配的内存。
另外就是整个代码里没有free()语句
实际上,我推荐直接学C++,而不是C,这些资源问题C++里用RAII都轻松搞定。当然,最重要的是要有资源的分配、释放要配对的意识。但用C是很容易在early return时漏写资源释放语句的。
二、
Mat_tra()这种简写命名,不推荐。因为过一阵你自己可能也未必能记住是什么的简写了,更别说别人了
三、学会使用clang-format格式化代码。顺带看一下clang-format里google style、llvm style里的变量和函数是怎么的命名风格,不要使用很多纯大写的变量名字。
【 在 sqsl 的大作中提到: 】
: 我写了一段计算矩阵的转置矩阵的程序,运行虽然没有报错,但是我觉得我程序里是不是有两个错误?
: (1)验证了if( AT == NULL )之后,没必要再验证if( AT[i] == NULL )吧?属于多此一举;
: (2)定义**XT后缺少生成2行5列的全零矩阵的步骤。程序这次虽然没有出错,但容易出现内存地址被占用的情况?
: ...................
--
修改:z16166 FROM 221.218.160.*
FROM 221.218.160.*
Chatgpt校正版:
#include <stdlib.h>
#include <stdio.h>
double** allocateMatrix(int rows, int cols) {
double **matrix = (double**) calloc(rows, sizeof(double*));
if (!matrix) {
printf("Memory allocation failed.\n");
return NULL;
}
for (int i = 0; i < rows; i++) {
matrix[i] = (double*) calloc(cols, sizeof(double));
if (!matrix[i]) {
printf("Memory allocation failed.\n");
while (i-- > 0) {
free(matrix[i]);
}
free(matrix);
return NULL;
}
}
return matrix;
}
void freeMatrix(double** matrix, int rows) {
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
}
double** transposeMatrix(double **matrix, int rows, int cols) {
double **transposed = allocateMatrix(cols, rows);
if (!transposed) return NULL;
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
transposed[i][j] = matrix[j][i];
}
}
return transposed;
}
void printMatrix(double **matrix, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%5.3g ", matrix[i][j]);
if ((cols != 1) && (j + 1) % cols == 0) {
printf("\n");
}
}
}
printf("\n");
}
void initializeMatrix(double **matrix, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0, value = i; j < cols; j++, value += j * j) {
matrix[i][j] = value;
}
}
}
int main() {
int rows = 2, cols = 5;
double **matrix, **transposed;
matrix = allocateMatrix(rows, cols);
if (!matrix) return 0;
initializeMatrix(matrix, rows, cols);
transposed = transposeMatrix(matrix, rows, cols);
if (!transposed) {
freeMatrix(matrix, rows);
return 0;
}
printMatrix(matrix, rows, cols);
printMatrix(transposed, cols, rows);
freeMatrix(matrix, rows);
freeMatrix(transposed, cols);
return 0;
}
【 在 sqsl 的大作中提到: 】
: 我写了一段计算矩阵的转置矩阵的程序,运行虽然没有报错,但是我觉得我程序里是不是有两个错误?
: (1)验证了if( AT == NULL )之后,没必要再验证if( AT[i] == NULL )吧?属于多此一举;
: (2)定义**XT后缺少生成2行5列的全零矩阵的步骤。程序这次虽然没有出错,但容易出现内存地址被占用的情况?
: ...................
--
FROM 192.102.204.*
你得把你输给chatgpt的指令列出来,那个更重要
【 在 forex 的大作中提到: 】
: Chatgpt校正版:
: #include <stdlib.h>
: #include <stdio.h>
: ...................
--
FROM 221.218.160.*