Фортран, передавая числа в подпрограммы

Уважаемые программисты на Фортране,

Я совершенно запутался с поведением следующего фрагмента простого кода на фортране.

  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)
Другие вопросы по тегам