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 ?
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
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 ?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.
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.
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