将二维数组作为参数传递给函数并获取另一个二维数组
Passing 2D arrays as argument to a function and get another 2D array
我正在编写一个代码来计算给定矩阵的逆矩阵,问题是,我需要将其包含在其他代码中以进行统计拟合,所以我需要类似函数的东西来接收大小矩阵(矩阵是方阵)和矩阵本身以及 returns 他的逆矩阵,我发现了一些关于语法的东西然后有了这个 (Gauss-Jordan)
float* inv(int n, float *A)
{
float* I = 0;//*
float aux;
float pivote;
for(int i = 0; i<n; i++){
for(int j = 0; j<n; j++){
if(i == j)
{
*(I+i*n+j) = 1.0; //*
}
else {
*(I+i*n+j) = 0.0;
}
}
}
for(int i = 0; i<n; i++)
{
pivote = *(A+i*n+i);
for(int k = 0; k<n; k++)
{
*(A+i*n+k) = *(A+i*n+k)/pivote;//*
*(I+i*n+k) = *(I+i*n+k)/pivote;//*
}
for(int j = 0; j<n; j++)
{
if(i!=j)
{
aux = *(A+j*n+i);//*
for(int k = 0; k<n;k++)
{
*(A+j*n+k)=*(A+j*n+k)-aux**(A+i*n+k);//*
*(I+j*n+k)=*(I+j*n+k)-aux**(I+i*n+k);//*
}
}
}
}
return I;//*
}
我把 //*
放在哪里是我有疑问的地方,语法是否正确?声明,在 return 中应该有其他东西,而不仅仅是 I
?。当我编译时出现分段错误,按照 Taekahn 的建议,使用消毒剂编译 g++ -fsanitize=address -fsanitize=undefined -fsanitize=leak inverse.cpp
我得到
inverse.cpp:148:28: runtime error: store to null pointer of type 'float'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11993==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040338c bp 0x7ffdd6a14510 sp 0x7ffdd6a144b0 T0)
==11993==The signal is caused by a WRITE memory access.
==11993==Hint: address points to the zero page.
#0 0x40338b in inv(int, float*) (/home/live/med_elect/a.out+0x40338b)
#1 0x402f30 in main (/home/live/med_elect/a.out+0x402f30)
#2 0x7f90ffed9e5a in __libc_start_main (/lib64/libc.so.6+0x23e5a)
#3 0x402289 in _start (/home/live/med_elect/a.out+0x402289)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/live/med_elect/a.out+0x40338b) in inv(int, float*)
==11993==ABORTING
如果你能帮助我,我真的很感激,非常感谢你,非常感谢你在评论中的反馈,我是新来的,有问题。
更新:感谢 nasy 的回答,重要的是要注意很多人都提到了矢量方法,因此,对于阅读本文的任何人,请查看评论并更好地尝试矢量方法。
在你的第二个函数中,你有 float *I = 0
。稍后,您尝试写入此数组但尚未分配它。您索引矩阵的方式是展平方法,因此您必须编写 float *I = new float[n*n]
。当然有不同的方法,比如评论中提到的使用动态二维数组、二维向量等。
问题 是指针 I
没有指向任何对象,并且您有以下语句:
*(I+i*n+j) = 1.0; //undefined behavior
以上语句导致未定义的行为。想象一下当 i
和 j
在第一次迭代中都是 0
时会发生什么。然后你取消引用 I
不指向任何 float
对象,因此这是未定义的行为。
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
所以您看到(也许看到)的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。在您的情况下,程序可能会崩溃。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
此外,使用 std::vector
比使用 new
和 delete
进行手动内存管理更好。
1有关未定义行为的更技术准确的定义,请参阅 this 其中提到:没有对程序行为的限制.
我正在编写一个代码来计算给定矩阵的逆矩阵,问题是,我需要将其包含在其他代码中以进行统计拟合,所以我需要类似函数的东西来接收大小矩阵(矩阵是方阵)和矩阵本身以及 returns 他的逆矩阵,我发现了一些关于语法的东西然后有了这个 (Gauss-Jordan)
float* inv(int n, float *A)
{
float* I = 0;//*
float aux;
float pivote;
for(int i = 0; i<n; i++){
for(int j = 0; j<n; j++){
if(i == j)
{
*(I+i*n+j) = 1.0; //*
}
else {
*(I+i*n+j) = 0.0;
}
}
}
for(int i = 0; i<n; i++)
{
pivote = *(A+i*n+i);
for(int k = 0; k<n; k++)
{
*(A+i*n+k) = *(A+i*n+k)/pivote;//*
*(I+i*n+k) = *(I+i*n+k)/pivote;//*
}
for(int j = 0; j<n; j++)
{
if(i!=j)
{
aux = *(A+j*n+i);//*
for(int k = 0; k<n;k++)
{
*(A+j*n+k)=*(A+j*n+k)-aux**(A+i*n+k);//*
*(I+j*n+k)=*(I+j*n+k)-aux**(I+i*n+k);//*
}
}
}
}
return I;//*
}
我把 //*
放在哪里是我有疑问的地方,语法是否正确?声明,在 return 中应该有其他东西,而不仅仅是 I
?。当我编译时出现分段错误,按照 Taekahn 的建议,使用消毒剂编译 g++ -fsanitize=address -fsanitize=undefined -fsanitize=leak inverse.cpp
我得到
inverse.cpp:148:28: runtime error: store to null pointer of type 'float'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11993==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040338c bp 0x7ffdd6a14510 sp 0x7ffdd6a144b0 T0)
==11993==The signal is caused by a WRITE memory access.
==11993==Hint: address points to the zero page.
#0 0x40338b in inv(int, float*) (/home/live/med_elect/a.out+0x40338b)
#1 0x402f30 in main (/home/live/med_elect/a.out+0x402f30)
#2 0x7f90ffed9e5a in __libc_start_main (/lib64/libc.so.6+0x23e5a)
#3 0x402289 in _start (/home/live/med_elect/a.out+0x402289)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/live/med_elect/a.out+0x40338b) in inv(int, float*)
==11993==ABORTING
如果你能帮助我,我真的很感激,非常感谢你,非常感谢你在评论中的反馈,我是新来的,有问题。
更新:感谢 nasy 的回答,重要的是要注意很多人都提到了矢量方法,因此,对于阅读本文的任何人,请查看评论并更好地尝试矢量方法。
在你的第二个函数中,你有 float *I = 0
。稍后,您尝试写入此数组但尚未分配它。您索引矩阵的方式是展平方法,因此您必须编写 float *I = new float[n*n]
。当然有不同的方法,比如评论中提到的使用动态二维数组、二维向量等。
问题 是指针 I
没有指向任何对象,并且您有以下语句:
*(I+i*n+j) = 1.0; //undefined behavior
以上语句导致未定义的行为。想象一下当 i
和 j
在第一次迭代中都是 0
时会发生什么。然后你取消引用 I
不指向任何 float
对象,因此这是未定义的行为。
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
所以您看到(也许看到)的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。在您的情况下,程序可能会崩溃。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
此外,使用 std::vector
比使用 new
和 delete
进行手动内存管理更好。
1有关未定义行为的更技术准确的定义,请参阅 this 其中提到:没有对程序行为的限制.