Fortran save statement

Czytałem o save oświadczenie w dokumencie referencyjnym (Intela) język, ale nie mogę do końca zrozumieć, co to robi. Czy mógłby mi ktoś wyjaśnić prostym językiem co to znaczy gdy save instrukcja jest dołączona do modułu ?

Author: High Performance Mark, 2010-05-23

4 answers

W principal gdy moduł wychodzi poza zakres, zmienne tego modułu stają się niezdefiniowane -- chyba że są zadeklarowane za pomocą atrybutu SAVE, lub używane jest polecenie SAVE. "Undefined" oznacza, że nie możesz polegać na zmiennej o poprzedniej wartości, jeśli ponownie użyjesz modułu-może ona mieć poprzednią wartość podczas ponownego dostępu do modułu, lub może nie -- nie ma gwarancji. Ale wiele kompilatorów nie robi tego dla modułu zmiennych -- zmienne prawdopodobnie zachowują swoje wartości - nie jest to warte wysiłku dla kompilatora, aby dowiedzieć się, czy moduł pozostaje w zakresie, czy nie i prawdopodobnie zmienne modułu są traktowane jako zmienne globalne-ale nie polegaj na tym! Aby być bezpiecznym, użyj "Zapisz" lub "użyj" modułu z głównego programu, aby nigdy nie wyszedł poza zakres.

"save" jest również ważne w procedurach, aby zapisać "state" pomiędzy wywołaniami podprogramu lub funkcji (jak napisał @ire_and_curses) -- " first invocation" inicjalizacje, liczniki, itp.

subroutine my_sub (y)

integer :: var
integer, save :: counter = 0
logical, save :: FirstCall = .TRUE.

counter = counter + 1

write (*, *) counter

if (FirstCall) then
   FirstCall = .FALSE.
   ....
end if

var = ....

Itd.

W tym fragmencie kodu, "licznik" będzie raportował liczbę wywołań podprogramu x. chociaż faktycznie w Fortran > = 90 można pominąć "save", ponieważ inicjalizacja w deklaracji implikuje"save".

W przeciwieństwie do przypadku modułu, w nowoczesnych kompilatorach, bez atrybutu save lub initialization-on-a-declaration, normalne jest, że lokalne zmienne procedur tracą swoje wartości na inwokacje. Jeśli więc spróbujesz użyć " var " w późniejszym wywołaniu przed ponownym zdefiniowaniem go w tym wywołaniu, wartość jest niezdefiniowana i prawdopodobnie nie będzie wartością obliczoną przy poprzednim wywołaniu procedury.

Różni się to od zachowania wielu kompilatorów FORTRAN 77, z których niektóre zachowały wartości wszystkich zmiennych lokalnych, mimo że nie było to wymagane przez standard języka. Niektóre stare programy zostały napisane w oparciu o to niestandardowe zachowanie - programy te zawiodą na nowszych kompilatorach. Wiele kompilatorów ma możliwość używania niestandardowego zachowania i "zapisywania" wszystkich zmiennych lokalnych.

Później EDIT: update z przykładem kodu, który pokazuje nieprawidłowe użycie zmiennej lokalnej, która powinna mieć atrybut save, ale nie:

module subs

contains

subroutine asub (i, control)

   implicit none

   integer, intent (in) :: i
   logical, intent (in) :: control

   integer, save :: j = 0
   integer :: k

   j = j + i
   if ( control ) k = 0
   k = k + i

   write (*, *) 'i, j, k=', i, j, k

end subroutine asub

end module subs

program test_saves

   use subs
   implicit none

   call asub ( 3, .TRUE. )
   call asub ( 4, .FALSE. )

end program test_saves

Zmienna lokalna k podprogramu jest celowo niewłaściwie używana-w tym programie inicjowana jest w pierwszym wywołaniu, ponieważ control jest prawdziwa, ale w drugim wywołaniu control jest FALSE, więc k nie jest przedefiniowane. Ale bez atrybutu save K {[7] } jest niezdefiniowany, więc używanie jego wartości jest nielegalne.

Kompilując program z gfortranem, stwierdziłem, że k i tak zachował swoją wartość:

 i, j, k=           3           3           3
 i, j, k=           4           7           7

Kompilując program z opcjami optymalizacji ifort i aggressive, K stracił swoją wartość:

 i, j, k=           3           3           3
 i, j, k=           4           7           4

Używając ifort z opcjami debugowania, problemy zostały wykryte podczas wykonywania!

 i, j, k=           3           3           3
forrtl: severe (193): Run-Time Check Failure. The variable 'subs_mp_asub_$K' is being used without being defined
 42
Author: M. S. B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-24 02:29:16

Wrzucam to jako odpowiedź Do M. S. B. bo brak formatowania w komentarzach pewnie zrobiłby z tego świńskie śniadanie :

Po pierwsze, dzięki za odpowiedź. Doceniam to.

If I understand right;

  subroutine save(j)
     implicit none      

     integer :: i = 0, j
     save i

     i = i + j
     write(*,*)i

  end subroutine save


  program test_save
     implicit none

     integer :: j

     j = 1

     call save(j)
     call save(j)

  end program test_save

Gdyby nie instrukcja SAVE w powyższym przykładzie, zmienna i (wartość zmiennej) zostałaby "utracona" po pierwszym wywołaniu podprogramu save. Dzięki niemu zachowuje swoją wartość - " 1 " w tym przypadku, a przez to zwiększa się do "2" podczas drugiego połączenia.

Czy dobrze zrozumiałem ? Może blisko ?
 4
Author: Friedrich Schwartz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-23 22:12:46

Zwykle zmienne lokalne wychodzą poza zakres po zakończeniu bieżącej procedury, a więc nie mają "pamięci" swojej wartości przy poprzednich wywołaniach. SAVE jest sposobem określenia, że zmienna w procedurze powinna zachować swoją wartość od jednego wywołania do następnego. Jest to przydatne, gdy chcesz zapisać stan w procedurze, na przykład, aby zachować działającą sumę lub utrzymać konfigurację zmiennej.

Jest dobre wyjaśnienie tutaj , z przykładem.

 3
Author: ire_and_curses,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-23 19:53:25

Krótkie wyjaśnienie może być następujące: atrybut save mówi, że wartość zmiennej musi być zachowana w różnych wywołaniach tego samego podprogramu / funkcji. W przeciwnym razie zwykle po powrocie z podprogramu/funkcji zmienne "lokalne" tracą swoje wartości, ponieważ pamięć, w której te zmienne były przechowywane, jest zwolniona. To jest jak static W C, jeśli znasz ten język.

 2
Author: ShinTakezou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-31 19:04:19