我正在尝试打印由Fortran90代码填充并以C代码分配的一维复数数组(c_double_complex)。
但是,当从Fortran代码传递数组后,用C(使用%f)在C中打印该数组时,仅打印该数组的第一个复数,其余为零。
我已经用整数和双精度进行了尝试,并且效果很好。
subroutine F_sub ( a, array ) bind (C, name="F_sub")
use, intrinsic :: iso_c_binding
implicit none
integer (c_int) :: a
complex (c_double_complex), dimension (a) :: array
array = [ 2.5 , 4.4 ]
a = 18
end subroutine F_sub
#include <stdio.h>
#include <stdlib.h>
void F_sub ( int *a, double _Complex * array_ptr );
int main ( void ) {
double _Complex * array_ptr;
int a;
a=2;
array_ptr = malloc (8* sizeof(double _Complex));
F_sub (&a, array_ptr);
printf ( "Values are: %f %f and a= %d\n", array_ptr [0], array_ptr [1] , a);
free(array_ptr);
return 0;
}
output: Values are: 2.500000 0.000000 and a= 18
有人可以告诉我上面代码中的问题在哪里吗?
答案 0 :(得分:0)
简单地说,printf()
的POSIX规范和Standard C specification都没有包含用于打印复数的任何转换格式。您必须将复数的实部和虚部分别传递给printf()
,并提供2个转换说明符。例如,您可以使用<complex.h>
中的cimag()
和creal()
以及通用格式%g
(+
确保始终有一个符号+
或-
):
printf("%g%+gi", creal(array_ptr[0]), cimag(array_ptr[0]));
我可能会为自己创建一个函数来处理复数的格式,并在各处使用它,而不是重复编写代码。
来自comment:
...我的担心与复数的印刷部分无关;这就是为什么C代码无法打印数组中的第二个数字(4.4),而只打印第一个数字(2.5)。
¶11共有三种复杂类型,分别命名为
float _Complex
,double _Complex
和long double _Complex
。 43)(复杂类型是实现的条件条件不需要支持;请参见6.10.8.3。)真正的浮动类型和复杂类型统称为浮动类型。¶12对于每种浮点类型,都有一个对应的实型,它始终是实浮点类型。对于真正的浮动类型,它是相同的类型。对于复杂类型,它是通过从类型名称中删除关键字
_Complex
给出的类型。¶13每个复杂类型都具有与数组类型相同的表示和对齐要求,而数组类型恰好包含相应实类型的两个元素。第一个元素等于复数的实部,第二个元素等于虚数。
因此,C复数被视为两个值的数组。在C代码中,array_ptr[0]
是一个复数。您应该使用creal()
和cimag()
或类似的函数从一个数字中取出两个部分。 AFAICS,您的Fortran函数(我只知道Fortran 77,我从未使用过Fortran 90,并且显示的代码与F77完全不同!)仅设置一个复数。因此,我不相信您可以访问array_ptr[1]
;您会得到不确定的行为。对于您为什么会得到明智的选择,我不确定我是否有很好的解释。我希望array_ptr[0]
等同于一个指针,并且代码不会打印它指向的数字。
我确实有gfortran
(来自GCC 8.3.0);我可以稍后再尝试您的代码。
我对发生的问题有令人讨厌的想法-我怀疑您需要一个小的变体:
double _Complex value;
F_sub(&a, &value);
printf("Values are: %f %f and a= %d\n", creal(value), cimag(value), a);
如果这是正确的,那么您将摆脱蓝色的谋杀(或不确定的行为),并且很不幸代码没有崩溃。还有可能您不需要&
中的&value
中的F_sub()
。
我还怀疑您代码中的free(array_ptr)
是错误的-我不明白为什么Fortran会分配空间。