Фортран, передавая числа в подпрограммы
Уважаемые программисты на Фортране,
Я совершенно запутался с поведением следующего фрагмента простого кода на фортране.
program foo
implicit double precision (a-h,p-w), integer*8(i-n),
+ character*12(x-z)
xx = 'not working '
call lskip(xx,4,8)
call lskip2(xx,4,8)
end
subroutine lskip(xxx,n,m)
implicit double precision (a-h,p-w), integer*8(i-n),
+ character*12(x-z)
print*, ' ine lskip ',xxx,n,m
return
end
subroutine lskip2(xxx,n,m)
character*(*) xxx
print*, ' ine lskip2 ',xxx,n,m
return
end
с gfortran-4.2.1
Он печатает что-то следующим образом.
ine lskip not working 7308894831428763652 17179869192
ine lskip2 not working 4 8
и с Intel ifort-12.1.2
вывод выглядит так;
ine lskip not working 34359738372 8
ine lskip2 not working 4 8
что не так с subroutine lskip()
? Почему я не могу использовать implicit declaration
опять в этом случае?
3 ответа
Вы передаете доброе целое число по умолчанию (обычно integer*4
) для integer*8
, поэтому представление целых чисел не совпадает, что приводит к мусору.
Во втором случае вы также используете целые числа по умолчанию в подпрограмме, так что все работает как положено. Если вы использовали переменные в основной программе для хранения значений для первого и второго аргумента, значения будут преобразованы в указанный вид:
i1 = 4
i2 = 8
call lskip(xx,i1,i2)
Компилятор не выдает предупреждение, но вы передаете здесь целочисленные литералы неправильной точности:
call lskip(xx,4,8)
подпрограмма lskip
ожидает, что аргументы integer*8
в то время как 4 и 8 имеют точность по умолчанию integer*4
,
Правильный вызов в этом случае может быть
call lskip(xx, 4_8, 8_8)
Однако, если это не какой-то устаревший код, переданный вам, я настоятельно рекомендую избегать написания любого кода в этом стиле, например Fortran 77 (исходный код с фиксированной формой, без модулей). Особенно, поскольку программы больше не должны помещаться на перфокартах, нигде не используйте неявную типизацию, поскольку это является источником многих зол.
Поэтому хорошей привычкой является включение этого в родительскую область ваших программ:
implicit none
Добавление к существующим ответам... Если программа написана для использования функций Fortran 90, компилятор автоматически найдет проблему. С подпрограммой в модуле и модулем use
По программе компилятор проверит аргументы на согласованность. Одна из многих причин перейти с Фортрана 77 на Фортран 90.
Быстрое преобразование в Фортран 90:
module MyStuff
contains
subroutine lskip(xxx,n,m)
implicit double precision (a-h,p-w), integer*8(i-n), character*12(x-z)
print*, ' ine lskip ',xxx,n,m
return
end
subroutine lskip2(xxx,n,m)
character*(*) xxx
print*, ' ine lskip2 ',xxx,n,m
return
end
end module MyStuff
program foo
use MyStuff
implicit double precision (a-h,p-w), integer*8(i-n), character*12(x-z)
xx = 'not working '
call lskip(xx,4,8)
call lskip2(xx,4,8)
end
Это преобразование не устраняет неявную типизацию, которая, я полностью согласен, никогда не должна использоваться.
И компиляция этой версии gfortran 4.9 говорит:
MyStuff.f90:22.17:
call lskip(xx,4,8)
1
Error: Type mismatch in argument 'n' at (1); passed INTEGER(4) to INTEGER(8)