почему не удается напечатать комплексное число при передаче его из фортрана в c

Я пытаюсь напечатать одномерный массив комплексных чисел (c_double_complex), который заполняется кодом Fortran90 и размещается в коде C.

Однако при печати массива на C (используя %f) после его передачи из кода на Фортране печатается только первое комплексное число массива, а остальное равно нулю.

Я пробовал это с целым и двойным числом, и это сработало нормально.

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

Может ли кто-нибудь сказать мне, где проблема в приведенных выше кодах?


person dev.robi    schedule 25.04.2019    source источник
comment
%f — это спецификатор формата для double, но вы передаете double _Complex. см. здесь предложения по печати комплексных чисел   -  person M.M    schedule 26.04.2019


Ответы (1)


Проще говоря, ни спецификация POSIX для printf(), ни Стандартная спецификация C включает любые форматы преобразования для печати комплексных чисел. Вам нужно будет передать действительную и мнимую части комплексного числа отдельно в printf() и предоставить 2 спецификатора преобразования. Например, вы можете использовать cimag() и creal() из <complex.h> и общий формат %g (+ гарантирует, что всегда знак, + или -):

printf("%g%+gi", creal(array_ptr[0]), cimag(array_ptr[0]));

Я бы, наверное, создал функцию для форматирования комплексных чисел и использовал бы ее везде, вместо того, чтобы постоянно писать код.


Из комментарий:

… меня беспокоит не печатная часть комплексного числа; речь идет о том, почему код C не может напечатать второе число (4.4) в массиве, а печатается только первое (2.5).

См. §6.2.5 Типы ¶11ff:

¶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) в вашем коде ошибочно — я не понимаю, зачем Фортрану выделять место.

person Jonathan Leffler    schedule 25.04.2019
comment
Я понимаю, о чем вы говорите. Но на самом деле мое беспокойство связано не с печатающей частью комплексного числа, а с тем, почему код C не может напечатать второе число (4.4) в массиве, а печатается только первое (2.5). - person dev.robi; 26.04.2019
comment
Я добавил в свой ответ некоторые неопределенные мысли - я не уверен, что вы получите уведомление о том, что я его отредактировал. Возможно, мне также придется отменить «дубликат». - person Jonathan Leffler; 26.04.2019
comment
да. Я пробовал, и это работает со мной. - person dev.robi; 28.04.2019