|
|||
|
Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
Here's a simple example: MODULE FOO_MODULE IMPLICIT NONE INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15) REAL(KIND=NP), PARAMETER :: PI=3.14_NP INTEGER :: K=0 END MODULE FOO_MODULE PROGRAM FOO USE foo_module IMPLICIT NONE REAL(KIND=NP) :: X, Y, Z ! Define Input Values X=2.0_NP Y=3.0_NP ! Print K WRITE(*,*)'BEFORE) K=',K ! Call Subroutine CALL FOO_FUN(X,Y,Z) ! Print K WRITE(*,*)'AFTER) K=',K END PROGRAM FOO SUBROUTINE FOO_FUN(X,Y,Z) USE foo_module IMPLICIT NONE REAL(KIND=NP), INTENT(IN) :: X, Y REAL(KIND=NP), INTENT(OUT) :: Z ! Compute Output Z Z=PI*X*Y ! Update K K=K+1 END SUBROUTINE FOO_FUN Compile: ifort foo_module.f90 foo.f90 -o foo.x Execution: BEFORE) K= 0 AFTER) K= 1 So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous. There is a way to permit to change the variables only explicitly? This problem is related to the SAVE attribute? |
|
|
||||
|
||||
|
|
|
|||
|
In article
<10008744.644.1335252224047.JavaMail.geo-discussion-forums@vbbfr18>, Marco Zannoni <marco.zannoni@gmail.com> writes: > So, if I understand correctly, every subroutine that USE a module, can > change the value of the variables defined into it. This can be useful, > but also dangerous. Right. That's pretty much one of the main points of modules. > There is a way to permit to change the variables only explicitly? What do you mean by "explicitly"? K=K+1 looks pretty explicit to me. > This problem is related to the SAVE attribute? No. The SAVE attribute means that the value remains defined until the next call of the routine. |
|
|||
|
Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende:
> Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them. > Here's a simple example: > > MODULE FOO_MODULE > IMPLICIT NONE > INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15) > REAL(KIND=NP), PARAMETER :: PI=3.14_NP > INTEGER :: K=0 > END MODULE FOO_MODULE > > PROGRAM FOO > USE foo_module > IMPLICIT NONE > REAL(KIND=NP) :: X, Y, Z > ! Define Input Values > X=2.0_NP > Y=3.0_NP > ! Print K > WRITE(*,*)'BEFORE) K=',K > ! Call Subroutine > CALL FOO_FUN(X,Y,Z) > ! Print K > WRITE(*,*)'AFTER) K=',K > END PROGRAM FOO > > SUBROUTINE FOO_FUN(X,Y,Z) > USE foo_module > IMPLICIT NONE > REAL(KIND=NP), INTENT(IN) :: X, Y > REAL(KIND=NP), INTENT(OUT) :: Z > ! Compute Output Z > Z=PI*X*Y > ! Update K > K=K+1 > END SUBROUTINE FOO_FUN > > Compile: > ifort foo_module.f90 foo.f90 -o foo.x > > Execution: > BEFORE) K= 0 > AFTER) K= 1 > > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous. > > There is a way to permit to change the variables only explicitly? > This problem is related to the SAVE attribute? If you want to limit the accessibility and use these variables only as a means to share information within the module, you can use the PRIVATE attribute or statement: integer, private :: k = 0 Then only routines in the module can access that particular variable k. (Routines that use the module, could define an alternative variable called "k" or acquire one from a different module, but this particular variable k will no longer be visible.) Regards, Arjen |
|
|||
|
On Apr 24, 12:23*am, Marco Zannoni <marco.zann...@gmail.com> wrote:
> Hi, I'm confused about the behavior of the variables defined in a module,in particular regarding the possibility to change them. > Here's a simple example: > > MODULE FOO_MODULE > * IMPLICIT NONE > * INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15) > * REAL(KIND=NP), PARAMETER :: PI=3.14_NP > * INTEGER :: K=0 > END MODULE FOO_MODULE > > PROGRAM FOO > * USE foo_module > * IMPLICIT NONE > * REAL(KIND=NP) :: X, Y, Z > * ! Define Input Values > * X=2.0_NP > * Y=3.0_NP > * ! Print K > * WRITE(*,*)'BEFORE) K=',K > * ! Call Subroutine > * CALL FOO_FUN(X,Y,Z) > * ! Print K > * WRITE(*,*)'AFTER) *K=',K > END PROGRAM FOO > > SUBROUTINE FOO_FUN(X,Y,Z) > * USE foo_module > * IMPLICIT NONE > * REAL(KIND=NP), INTENT(IN) *:: X, Y > * REAL(KIND=NP), INTENT(OUT) :: Z > * ! Compute Output Z > * Z=PI*X*Y > * ! Update K > * K=K+1 > END SUBROUTINE FOO_FUN > > Compile: > ifort foo_module.f90 foo.f90 -o foo.x > > Execution: > *BEFORE) K= * * * * * 0 > *AFTER) *K= * * * * * 1 > > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous. > > There is a way to permit to change the variables only explicitly? I am not certain what you mean. You might want to look into the PROTECTED attribute. You could make the module variables PRIVATE, and use assessor functions and updater subroutines to get and set their values. Bob Corbett |
|
|||
|
Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:
> Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende: > > Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them. > > Here's a simple example: > > > > MODULE FOO_MODULE > > IMPLICIT NONE > > INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15) > > REAL(KIND=NP), PARAMETER :: PI=3.14_NP > > INTEGER :: K=0 > > END MODULE FOO_MODULE > > > > PROGRAM FOO > > USE foo_module > > IMPLICIT NONE > > REAL(KIND=NP) :: X, Y, Z > > ! Define Input Values > > X=2.0_NP > > Y=3.0_NP > > ! Print K > > WRITE(*,*)'BEFORE) K=',K > > ! Call Subroutine > > CALL FOO_FUN(X,Y,Z) > > ! Print K > > WRITE(*,*)'AFTER) K=',K > > END PROGRAM FOO > > > > SUBROUTINE FOO_FUN(X,Y,Z) > > USE foo_module > > IMPLICIT NONE > > REAL(KIND=NP), INTENT(IN) :: X, Y > > REAL(KIND=NP), INTENT(OUT) :: Z > > ! Compute Output Z > > Z=PI*X*Y > > ! Update K > > K=K+1 > > END SUBROUTINE FOO_FUN > > > > Compile: > > ifort foo_module.f90 foo.f90 -o foo.x > > > > Execution: > > BEFORE) K= 0 > > AFTER) K= 1 > > > > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous. > > > > There is a way to permit to change the variables only explicitly? > > This problem is related to the SAVE attribute? > > If you want to limit the accessibility and use these variables only as a > means to share information within the module, you can use the PRIVATE > attribute or statement: > > integer, private :: k = 0 > > Then only routines in the module can access that particular variable k. > (Routines that use the module, could define an alternative variable called "k" > or acquire one from a different module, but this particular variable k will > no longer be visible.) > > Regards, > > Arjen Thanks, this was exaclty what I was looking for. |
|
|||
|
On 04/24/2012 11:38 AM, Marco Zannoni wrote:
> Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto: >> Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende: >>> Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them. >>> Here's a simple example: [...] >> If you want to limit the accessibility and use these variables only as a >> means to share information within the module, you can use the PRIVATE >> attribute or statement: >> >> integer, private :: k = 0 >> >> Then only routines in the module can access that particular variable k. >> (Routines that use the module, could define an alternative variable called "k" >> or acquire one from a different module, but this particular variable k will >> no longer be visible.) >> >> Regards, >> >> Arjen > > Thanks, this was exaclty what I was looking for. You may consider setting the _default_ accessibility of all module entities to private, and mark only those entities as public that you really need outside the module. My personal preference is to avoid module variables altogether where possible. When they are necessary, give them verbose names to minimize the impact of missing declarations and typos. -- Wolfgang -- E-mail: firstnameinitial.lastname@domain.de Domain: yahoo |
|
|||
|
Wolfgang Kilian <seesig@domain.invalid> wrote:
> On 04/24/2012 11:38 AM, Marco Zannoni wrote: > > Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto: > >> If you want to limit the accessibility and use these variables only as a > >> means to share information within the module, you can use the PRIVATE > >> attribute or statement: > >> > >> integer, private :: k = 0 > > Thanks, this was exaclty what I was looking for. > > You may consider setting the _default_ accessibility of all module > entities to private, and mark only those entities as public that you > really need outside the module. That's what I recommend. To do so, just use the PRIVATE statement with no particular entities specified, as in just private This goes right by the "implicit none" (which I do see that the OP uses). With modules, "implicit none" becomes even more important because without it you can't easily tell whether a variable is implicitly declared or accessed from a module. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
In article <1kj1pyw.s6yvn6r10s8gN%nospam@see.signature>,
nospam@see.signature (Richard Maine) wrote: > Wolfgang Kilian <seesig@domain.invalid> wrote: > > > On 04/24/2012 11:38 AM, Marco Zannoni wrote: > > > Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto: > > > >> If you want to limit the accessibility and use these variables only as a > > >> means to share information within the module, you can use the PRIVATE > > >> attribute or statement: > > >> > > >> integer, private :: k = 0 > > > > Thanks, this was exaclty what I was looking for. > > > > You may consider setting the _default_ accessibility of all module > > entities to private, and mark only those entities as public that you > > really need outside the module. > > That's what I recommend. To do so, just use the PRIVATE statement with > no particular entities specified, as in just > > private > > This goes right by the "implicit none" (which I do see that the OP > uses). With modules, "implicit none" becomes even more important because > without it you can't easily tell whether a variable is implicitly > declared or accessed from a module. There are two aspects of the original question. One if if you are writing a module that will be used by other programmers, and you want to protect the module variables that are intended to be shared only within the module. I think the above comments address mostly this situation. You declare some or all of the module variables to be private, and except for some trickery, those variables will not be visible or accessible directly outside of the module. The "trickery" involves pointers or using those private variables as actual arguments to other subroutines (which then can modify them, perhaps intentionally or perhaps by mistake). The other situation is when you are on the other side and you are USEing a module (written by you or by someone else). If you don't want to modify any of the module variables by mistake, and you want the compiler to help you avoid doing that, then you can develop the programming habit of always using the ONLY clause with the USE statements. This is useful in several ways. In addition to the unintentional modification problems this avoids, it also documents in the USEing subroutine exactly where particular variables live (or at least how you are accessing them, which is not quite the same thing, but you probably see the difference). Consider the following use mod1 use mod2 use mod3 implicit none ... k = k + 1 ... You know that "k" must be in one of those modules because otherwise the compiler would complain (due to the implicit none and the lack of a local declaration). But you don't know which one, and to track it down you would need to search through the source to all those modules (or worse, dig down several levels of modules to find it, with the breadth of your search increasing exponentially with the depth). If instead, you had written use mod1, only: a, b, c use mod2, only: i, j, k use mod3, only: x, y, z ... then it would be clear at a glance how "k" became accessible in your code. If you then look in module mod2, and if it also uses ONLY clauses like this, then you could quickly track down exactly where that variable was declared. You could also search your code for other "use mod2" statements to see where else that variable has been made accessible. As nice as all this sounds, one complaint I have is that it is simply a programming convention. If you slip up somewhere and USE mod2 without the only clause, then you are back with all of the original problems. You just shot yourself in the foot, and you might not know about it until some multiday debugging excursion to track down some problem with a variable being modified. Currently, there is no way to enforce the requirement that ONLY clauses must be used (say, IMPLICIT ONLY NONE or REQUIRE ONLY or some similar declaration) so that the compiler can help you enforce this. You are just on your own to try to enforce your chosen programming convention with little or no additional help available from the compiler. $.02 -Ron Shepard |
|
|||
|
On Tuesday, April 24, 2012 6:38:47 PM UTC+9, Marco Zannoni wrote:
> Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto: > > Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende: > > > Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them. > > > Here's a simple example: > > > > > > MODULE FOO_MODULE > > > IMPLICIT NONE > > > INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15) > > > REAL(KIND=NP), PARAMETER :: PI=3.14_NP > > > INTEGER :: K=0 > > > END MODULE FOO_MODULE > > > > > > PROGRAM FOO > > > USE foo_module > > > IMPLICIT NONE > > > REAL(KIND=NP) :: X, Y, Z > > > ! Define Input Values > > > X=2.0_NP > > > Y=3.0_NP > > > ! Print K > > > WRITE(*,*)'BEFORE) K=',K > > > ! Call Subroutine > > > CALL FOO_FUN(X,Y,Z) > > > ! Print K > > > WRITE(*,*)'AFTER) K=',K > > > END PROGRAM FOO > > > > > > SUBROUTINE FOO_FUN(X,Y,Z) > > > USE foo_module > > > IMPLICIT NONE > > > REAL(KIND=NP), INTENT(IN) :: X, Y > > > REAL(KIND=NP), INTENT(OUT) :: Z > > > ! Compute Output Z > > > Z=PI*X*Y > > > ! Update K > > > K=K+1 > > > END SUBROUTINE FOO_FUN > > > > > > Compile: > > > ifort foo_module.f90 foo.f90 -o foo.x > > > > > > Execution: > > > BEFORE) K= 0 > > > AFTER) K= 1 > > > > > > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous. > > > > > > There is a way to permit to change the variables only explicitly? > > > This problem is related to the SAVE attribute? > > > > If you want to limit the accessibility and use these variables only as a > > means to share information within the module, you can use the PRIVATE > > attribute or statement: > > > > integer, private :: k = 0 > > > > Then only routines in the module can access that particular variable k. > > (Routines that use the module, could define an alternative variable called "k" > > or acquire one from a different module, but this particular variable k will > > no longer be visible.) > > > > Regards, > > > > Arjen > > Thanks, this was exaclty what I was looking for. Also, since no-one else mentioned it, while you're writing such code pleasenote that you can avoid other potential problems by making FOO_FUN into a module procedure or into an internal procedure. That will prevent you from making undetected and hard-to-debug errors with prcedure interfaces. Regards, Mike Metcalf |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|