> Правила вызова функций в си определяются стандартом. Правила вызова функций в фортране определяются компилятором. Именно поэтому...............
Вот пример вызова фортрановской процедуры из си:
Код:
#include <string.h>
#include <stdlib.h>
struct MyStruct
{
int Field1;
double Field2;
char Field3[25];
};
int main()
{
int *Arr,x;
char st[] = "Hello World!\0";
struct MyStruct S;
S.Field1 = 5;
S.Field2 = 3.14;
x = 12;
Arr = (int *) malloc(12 * sizeof (int));
for (i = 0;i<12;i++) Arr[i] = i;
strcpy(S.Field3,"World, hello again!");
ffunc_(st,&x,Arr,&S);
free(Arr);
return 0;
}
Код:
subroutine ffunc(x,y,Arr,S)
type MyType
integer Field1
double precision Field2
character(25) Field3
end type MyType
type(MyType) S
character(*) x
integer y,Arr(12)
print *,x(1:12)
print *,y
print *,Arr
print *,S%Field1
print *,S%Field2
print *,S%Field3
end subroutine ffunc
Мы должны следить за соответствием типов, за соблюдением размеров массивов (их придется передавать). Что еще надо держать в голове? Конечно же мы не можем передавать массив, как assumed shape, - это чисто фортрановская фича. Заметьте, корректно передаются не только скаляры, массивы и строки, но и структуры. Конечно, нужно следить, за тем, чтобы не сделать вызов типа f(5). И никакой зависимости от компилятора нет.
Многомерные массивы в си. Массивы размера, задаваемого на этапе компиляции полезны редко. На практике обычно используются одномерные динамические массивы.
> Если заранее знать, что задачи будут ограничены только линейкой -- у фортрана есть некоторое преимущество
Огромное преимущество. В си на каждый чих придется лепить циклы. Код на фортране за счет векторных операций, срезов массивов и специальных конструкций будет в разы короче.
Вот вам перемножение матриц:
Код:
for (i=0;i<N;i++)
for (j=0;j<N;j++)
for (k=0;k<N;k++)
C[i+N*j] += A[k+N*j]*B[i+k*N]
и фортрановская версия:
Код:
forall(i = 1:N,j = 1:N) C(i,j) = sum(A(:,j)*B(i,:))
> как просто на нём передать функцию
Очень просто:
Код:
module MyModule
contains
function f(x) result(y)
integer x,y
y = x+1
end function f
subroutine calc(x,myfunc)
integer x
interface
function myfunc(x) result(y)
integer x,y
end function myfunc
end interface
print *,myfunc(x)
end subroutine calc
end module MyModule
use MyModule
integer :: a = 5
call calc(a,f)
end
Можно описать mufunc просто как extern, но это моветон.
> как элегантно на нём создавать новые типы
Ну так type. Процедуры туда тоже можно инкапсулировать. Имеется возможность перегрузки операторов и пр.
Для оперирования рекурсивными структурами - вся та же фигня с указателями, как и в си.
С компиляторами - да, ситуация не очень. gfortran не слишком-то качественный код генерит.
С другой стороны, все компиляторы, что я пробовал, весьма нестроги. ifort, например, совсем откровенные ляпы пропускает даже с -warn all. С си ситуация не лучше.
> тяжёлым наследием 66-го.
Ну да, implicit none везде писать приходится. А какое еще наследие? Репутация - это да. Многие, поработав с 77м при слове "фортран"... дальше слушать ничего не хотят
> В фортране не стандартизированы ни вызовы функций ни...
Тут нужны примеры или ссылки. Выше я уже привел пример вызова из си. При использовании какого компилятора он не будет работать?