На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
    > 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"
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0418 ]   [ 15 queries used ]   [ Generated: 4.03.24, 08:18 GMT ]