На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > FORTRAN: как объявить глобальные переменные?
      Допустим, имеем такую конструкцию:

      ExpandedWrap disabled
        Program qwe
           implicit none
           real ar(5,5)
           real q
         
           CALL subrt
         
        end
         
        subroutine subrt
           implicit none
           real b
           real c
           b=ar(2,4)/2
        end


      При запуске подобного кода Фортран (Powerstation, 1996) говорит, что в subrt переменная ar не является массивом. Т.е. язык не понимает, что я хотел бы видеть массив ar как глобальную переменную. Порыл документацию, там предлагают использовать оператор COMMON. Если я пишу строку "COMMON ar" после строки объявления этого массива, ничего не меняется. Что я делаю не так?

      PS дополнительный вопрос. Допустим, с первой частью вопроса все решилось и в подпрограмме ar успешно используется. Что будет, если в этом случае я объявлю в подпрограмме еще один массив ar? Будет использоваться локальный массив?

      Не пинайте сильно, с фортраном столкнулся по инженерной работе в виде стандарта по предприятию. Сам больше по VB и совсем немножко по C++.
        COMMON-блок надо определять вне программ, подпрограмм и функций. Грубо говоря, COMMON-блок - это аналог глобальной структуры в C. Но вроде бы для того, чтобы програмный модуль его увидел, его надо повторно описать, хотя в совр. компиляторах возможно и не надо. Ну это типа как дефиниции и декларации в C. Да, COMMON-блок может быть именованным и не именованным.

        Конкретный синтаксис уже не помню, но если не решил еще вопрос, могу глянуть в старых записях, а где-то у меня на дискетах и огромный вычислительный проект был, но рыться надо.

        Добавлено
        Цитата SO @
        PS дополнительный вопрос. Допустим, с первой частью вопроса все решилось и в подпрограмме ar успешно используется. Что будет, если в этом случае я объявлю в подпрограмме еще один массив ar? Будет использоваться локальный массив?

        Скорее всего объявить ar просто не получиться, переменные, декларированые в подпрограмме как переменные коумон-блока, используются далее без разыменовывания, так, как будто они тут и описаны, но находятся они физически в глобальной области. Так что завести вторую переменную с тем же идентификатором не получится. Но это в классических версиях Фортрана, сейчас может быть и по другому, надо экспериментировать.
          SO
          ExpandedWrap disabled
            program qwe
               implicit none
               real ar(5,5)
               real q
             
               CALL subrt
             
            containts
             
              subroutine subrt
                implicit none
                real b
                real c
                b=ar(2,4)/2
              end subroutine subrt
             
            end program qwe
          Сообщение отредактировано: NetVir -
            COMMON-блок определяет внешнее имя. К этому имени привязываются некоторые описанные в программе переменные (которые и составляют COMMON-блок). Не знаю зачем так было сделано, наверно в старые времена линковщик не поддерживал большого количества внешних имен для данных.

            Получалось что-то вроде
            ExpandedWrap disabled
                    REAL*4 ARR(10)
                    INTEGER*4 CNT
                    COMMON EXTNM/ARR,CNT/

            Писать можно и внутри процедур (даже нужно), но видна эта конструкция будет только в процедуре.

            При этом в другом файле можно написать и по другому
            ExpandedWrap disabled
                    REAL*4 AR(10)
                    INTEGER*4 CNTR
                    COMMON EXTNM/AR,CNTR/

            AR при этом будет совпадать с ARR, а CNTR c CNT

            Можно даже размер массива другой взять, то тогда адреса поползут
              Всем большое спасибо!

              Совет NetVir непосредственно сработал. С Common попытаюсь позже разобраться.
                Лучше разберись с модулями - это удобнее, чем всякие COMMON-блоки. Кроме того, там кроме глобальных переменных и другие интересные вещи есть.
                  1. COMMON-блок в настоящее время считается устаревшей конструкцией. Вместо него рекомендуется использовать MODULE.
                  2. Описывается примерно так:

                  subroutine MySub
                  integer a(10)
                  real*8 b
                  common /MyCommon/ a,b
                  ...
                  return
                  end

                  program MyProg
                  real*6 c(6)
                  common /MyCommon/ c
                  ...
                  stop
                  end

                  в данном случае мы организовали COMMON-блок длиной 48 байтов, причем эти байты в подпрограмме фигурируют как целочисленный массив и переменная двойной точности, а в основной программе - как массив двойной точности. Т.е. один и тот же блок памяти используется в разных программных единицах для хранения данных разных типов.
                  В старые времена это позволяло экономить память, но сейчас способствует возникновению труднообнаружимых ошибок.
                    Цитата andriano @
                    В старые времена это позволяло экономить память, но сейчас способствует возникновению труднообнаружимых ошибок.
                    Не совсем верно. COMMON-блок все-таки чаще использовался для обмена данными.
                    Есть еще EQUIVALENCE, позволял сделать что-то вроде union. Обычно использовался только для доступа к внутренностям данных (чтобы прочитать например вещественное как набор байтов). Тоже может сэкономить память.
                    Но ошибок с ними обоими действительно можно огрести слишком много.
                      ExpandedWrap disabled
                        module constants
                        real, parameter :: c = 2.99792458e8
                        real, parameter :: pi = 3.14159265
                        real, parameter :: mu_0 = pi*4.0e-7
                        end module constants
                         
                        subroutine print_constants
                        use constants
                        write (*,*) 'speed of light in vacuum: ', c
                        write (*,*) 'magnetic permeability: ', mu_0
                        end subroutine print_constants
                         
                        program test_constants
                        call print_constants
                        end


                      Возвращаясь к исходному примеру кода, хочу заметить, что "хорошим тоном" является передача параметров внутрь подпрограмм, а не использование глобальных переменных. Т.е. следует объявить массив ar параметром подпрограммы subrt
                        Тем более, что с некоторых пор фортран позволяет структурировать данные подобно языкам Паскаль или См
                          Цитата tulebaev @
                          Возвращаясь к исходному примеру кода, хочу заметить, что "хорошим тоном" является передача параметров внутрь подпрограмм, а не использование глобальных переменных. Т.е. следует объявить массив ar параметром подпрограммы subrt


                          Дело в том, что на деле подпрограмма, в зависимости от аргументов, меняет содержимое массива, который впоследствии будет использован в основной программе. Тут подошел бы вариант вроде передачи указателей на массивы в качестве аргументов. Но умеет ли такое фортран?
                          Сообщение отредактировано: SO -
                            Это в фортране поведение по умолчанию. Это чтобы передать через параметр значение надо параметр как-то специально обозначать
                              Цитата amk @
                              как-то специально обозначать
                              intent(in/out/inout)
                                Цитата SO @
                                Тут подошел бы вариант вроде передачи указателей на массивы в качестве аргументов. Но умеет ли такое фортран?

                                Цитата SO @
                                Это в фортране поведение по умолчанию.

                                Угу. Более того, в "классических" фортранах и переменные и даже константы передаются по указателю - типа как ссылки C++.
                                  Не по указателю, а по ссылке. Указателями они выглядят в C-процедурах.

                                  Вообще передача по ссылкам констант иногда приводит к странному поведению программ.
                                  Так
                                  ExpandedWrap disabled
                                    PROCEDURE INC(X,Y)
                                    REAL X,Y
                                    X=X+Y
                                    END
                                     
                                    INC(2.0,1.0)
                                    PRINT *,2.0
                                  может неожиданно для всех вывести "3"
                                    Цитата amk @
                                    Не по указателю, а по ссылке.

                                    Я имел в виду, что физически передается указатель, который автоматически разыменовывается - ну да, это называется передать по ссылке.

                                    Цитата amk @
                                    Вообще передача по ссылкам констант иногда
                                    приводит к странному поведению программ.

                                    ...

                                    Ага - это пример из букваря. У меня где-то целая книжка приколов на Фортране валялась.
                                      Спасибо за разъяснения про передачу данных по умолчанию.

                                      У меня есть еще один небольшой вопрос не совсем по теме, но по Фортрану. Я использую Fotran Power Station (Developer Studio) 1996 года выпуска. Для тех программ, которые пишутся для инженерных расчетов, как правило, достаточно консольного ввода-вывода, причем зачастую не нужен даже интерфейс. Другими словами, Power Station меня вполне устраивает по своим возможностям и, если закрыть глаза на мелочи, даже своим IDE. Но есть проблема.

                                      Имеются 4 компьютера, на всех стоит Windows XP SP3. На рабочем и двух других - русская, на одном - английская. Имеется один и тот же дистрибутив, устанавливаемый на все четыре машины. Казалось бы, все должно быть идентично, однако на всех компьютерах, кроме рабочего, у установленного фортрана имеется одна особенность: не работает отладка ни в каком виде. К примеру, я ставлю обычный брекпоинт (F8), запускаю программу всеми возможными способами - программа на брекпоинте не останавливается. Или другой пример - пробую выполнить команду "Run To Cursor" - программа выполняется целиком без всякой остановки.

                                      Как понимаете, писать программу в таких условиях тяжело. В чем проблема и как ее решить?
                                      Сообщение отредактировано: SO -
                                        > ...не работает отладка ни в каком виде
                                        По умолчанию стоит опция "компилировать окончательную версию" (release, not debug)
                                        См. ключи, передаваемые компилятору
                                          Цитата tulebaev @
                                          > ...не работает отладка ни в каком виде
                                          По умолчанию стоит опция "компилировать окончательную версию" (release, not debug)
                                          См. ключи, передаваемые компилятору

                                          Посмотрел, вроде бы, везде, где можно. В настройках (см. приложенные рисунки) везде Debug, в программе никаких параметров компилятору не передается. Да и мистика-то в том, что на одной из четырех машин отладка работает нормально (дистрибутив один и тот же, свежепоставленный фортран).

                                          PS кое-как проблему можно "решить", используя pause, но это все равно не то.
                                          Прикреплённый файлПрикреплённый файлfd1.PNG (4,56 Кбайт, скачиваний: 366)
                                          Прикреплённый файлПрикреплённый файлfd2.PNG (4,08 Кбайт, скачиваний: 391)
                                          Прикреплённый файлПрикреплённый файлfd3.PNG (11,74 Кбайт, скачиваний: 368)
                                            При компиляции программ используются makefile -- параметры оттуда имеют приоритет перед опциями IDE (деталей не помню, так как пользовался FPS весьма давно).
                                            Если не очень сильно привязаны к компилятору от Microsoft, то можно установить GNUFortran и для отладки использовать gdb
                                            1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                            0 пользователей:


                                            Рейтинг@Mail.ru
                                            [ Script execution time: 0,0456 ]   [ 16 queries used ]   [ Generated: 15.06.25, 09:32 GMT ]