Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.166.7] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Допустим, имеем такую конструкцию:
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++. |
Сообщ.
#2
,
|
|
|
COMMON-блок надо определять вне программ, подпрограмм и функций. Грубо говоря, COMMON-блок - это аналог глобальной структуры в C. Но вроде бы для того, чтобы програмный модуль его увидел, его надо повторно описать, хотя в совр. компиляторах возможно и не надо. Ну это типа как дефиниции и декларации в C. Да, COMMON-блок может быть именованным и не именованным.
Конкретный синтаксис уже не помню, но если не решил еще вопрос, могу глянуть в старых записях, а где-то у меня на дискетах и огромный вычислительный проект был, но рыться надо. Добавлено Цитата SO @ PS дополнительный вопрос. Допустим, с первой частью вопроса все решилось и в подпрограмме ar успешно используется. Что будет, если в этом случае я объявлю в подпрограмме еще один массив ar? Будет использоваться локальный массив? Скорее всего объявить ar просто не получиться, переменные, декларированые в подпрограмме как переменные коумон-блока, используются далее без разыменовывания, так, как будто они тут и описаны, но находятся они физически в глобальной области. Так что завести вторую переменную с тем же идентификатором не получится. Но это в классических версиях Фортрана, сейчас может быть и по другому, надо экспериментировать. |
Сообщ.
#3
,
|
|
|
SO
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 |
Сообщ.
#4
,
|
|
|
COMMON-блок определяет внешнее имя. К этому имени привязываются некоторые описанные в программе переменные (которые и составляют COMMON-блок). Не знаю зачем так было сделано, наверно в старые времена линковщик не поддерживал большого количества внешних имен для данных.
Получалось что-то вроде REAL*4 ARR(10) INTEGER*4 CNT COMMON EXTNM/ARR,CNT/ Писать можно и внутри процедур (даже нужно), но видна эта конструкция будет только в процедуре. При этом в другом файле можно написать и по другому REAL*4 AR(10) INTEGER*4 CNTR COMMON EXTNM/AR,CNTR/ AR при этом будет совпадать с ARR, а CNTR c CNT Можно даже размер массива другой взять, то тогда адреса поползут |
Сообщ.
#5
,
|
|
|
Всем большое спасибо!
Совет NetVir непосредственно сработал. С Common попытаюсь позже разобраться. |
Сообщ.
#6
,
|
|
|
Лучше разберись с модулями - это удобнее, чем всякие COMMON-блоки. Кроме того, там кроме глобальных переменных и другие интересные вещи есть.
|
Сообщ.
#7
,
|
|
|
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 байтов, причем эти байты в подпрограмме фигурируют как целочисленный массив и переменная двойной точности, а в основной программе - как массив двойной точности. Т.е. один и тот же блок памяти используется в разных программных единицах для хранения данных разных типов. В старые времена это позволяло экономить память, но сейчас способствует возникновению труднообнаружимых ошибок. |
Сообщ.
#8
,
|
|
|
Цитата andriano @ Не совсем верно. COMMON-блок все-таки чаще использовался для обмена данными.В старые времена это позволяло экономить память, но сейчас способствует возникновению труднообнаружимых ошибок. Есть еще EQUIVALENCE, позволял сделать что-то вроде union. Обычно использовался только для доступа к внутренностям данных (чтобы прочитать например вещественное как набор байтов). Тоже может сэкономить память. Но ошибок с ними обоими действительно можно огрести слишком много. |
Сообщ.
#9
,
|
|
|
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 |
Сообщ.
#10
,
|
|
|
Тем более, что с некоторых пор фортран позволяет структурировать данные подобно языкам Паскаль или См
|
Сообщ.
#11
,
|
|
|
Цитата tulebaev @ Возвращаясь к исходному примеру кода, хочу заметить, что "хорошим тоном" является передача параметров внутрь подпрограмм, а не использование глобальных переменных. Т.е. следует объявить массив ar параметром подпрограммы subrt Дело в том, что на деле подпрограмма, в зависимости от аргументов, меняет содержимое массива, который впоследствии будет использован в основной программе. Тут подошел бы вариант вроде передачи указателей на массивы в качестве аргументов. Но умеет ли такое фортран? |
Сообщ.
#12
,
|
|
|
Это в фортране поведение по умолчанию. Это чтобы передать через параметр значение надо параметр как-то специально обозначать
|
Сообщ.
#13
,
|
|
|
Цитата amk @ intent(in/out/inout) как-то специально обозначать |
Сообщ.
#14
,
|
|
|
Цитата SO @ Тут подошел бы вариант вроде передачи указателей на массивы в качестве аргументов. Но умеет ли такое фортран? Цитата SO @ Это в фортране поведение по умолчанию. Угу. Более того, в "классических" фортранах и переменные и даже константы передаются по указателю - типа как ссылки C++. |
Сообщ.
#15
,
|
|
|
Не по указателю, а по ссылке. Указателями они выглядят в C-процедурах.
Вообще передача по ссылкам констант иногда приводит к странному поведению программ. Так PROCEDURE INC(X,Y) REAL X,Y X=X+Y END INC(2.0,1.0) PRINT *,2.0 |