Prev: Clarify An Old Question: define a user data containing array with dimensions decided in running time
Next: parameter inconsistency (now adjustable dimensions of arguments)
From: dpb on 19 May 2010 15:21 ivan martin wrote: .... > ... I was wondering why when we do the above, > in the main program need to state that something is a parameter > > INTEGER, PARAMETER : N > > but in the subroutine we just state > > INTEGER, INTENT(IN) :: N > > (e.g. we don't say that N is a parameter). > > Parameter == named constant ? Maybe ? But why does then work in the main program > just to write > > INTEGER :: N=100 > > (e.g. this is also a named constant). No, the latter is _NOT_ a named constant; it's an integer variable. The difference is that after INTEGER, PARAMETER :: N = 100 in a program unit an assignment statement or other attempt to modify N such as N = 200 will result in a compiler error letting you know you screwed up in trying to modify a value that was intended as a constant. OTOH, INTEGER :: N=100 is a declaration of an (default length) integer variable with an initialization expression setting its starting value. But, you could follow this by another assignment statement N = 200 and it would from that point in program execution (until changed again, perhaps) have the new value of 200. Two completely different things, parameters and variables. --
From: glen herrmannsfeldt on 19 May 2010 17:17 ivan martin <i.martin(a)invalid.com> wrote: > On Wed, 19 May 2010 12:44:42 -0500, mecej4 <mecej4_no_spam(a)operamail.com> wrote: >>On 5/19/2010 12:26 PM, ivan martin wrote: >>> Maybe a naive question, but why do we need when in main program >>> !************ >>> integer, parameter :: n=100 >>> real, dimension(n) :: my_array >>> but when in a subroutine >>> subroutine my_subroutine(n,array) >>> integer, intent(in) :: n >>> real, dimension(n), intent(inout) :: array >>> e.g. where did the "parameter" go ? >>> (I'm sure you understand what I'm aiming on by now) >>> Shouldn't parameter keyword be used every time we wish to, >>> for example, declare an array ? >>That is a valid, if naive, question. >>The use of a parameter (named constant) is not required, but using one >>makes the code more readable and easier to modify. If I have 15 arrays >>of size 100, and I want one day to enlarge them to size 200, with the >>declared parameter I change one instance of 100 to 200, instead of 15 >>instances of 100. > You misunderstood though - I probably could've putted the question > better also. I wasn't asking why about declaring size of arrays > with parameters, instead of explcitly writing them out in > declarations, but something else. I was wondering why when we do > the above, in the main program need to state that something is > a parameter They are very different, and the difference goes back at least to Fortran 66. In both cases the size has to be known before entering the routine. For MAIN, that means known at compile time. Space is actually allocated for the array, potentially in static allocation memory. In the subroutine, no space is allocated for the array, at least not in most cases. For the give problem, it would work just as well if the one in the subroutine said: real, dimension(*), intent(inout) :: array (well, not in Fortran 66, but (1) was often used.) Fortran 66 and 77 allow for implementation with only static allocation. Since the subroutine is using the allocated space from the calling routine, it isn't allocating anything for the array, and so it is allowed for the dimension to be a variable. That variable much have a value before the subroutine is called. Note that newer versions of Fortran allow for automatic arrays using the size passed as an argument. It might even be possible that automatic arrays in MAIN could be allocated based on command line parameters, or environment variables. In any case, the size of a static array needs to be known at compile time, and the size of an automatic array needs to be known at block entry. -- glen
From: Craig Powers on 19 May 2010 18:05 ivan martin wrote: > Maybe a naive question, but why do we need when in main program > !************ > integer, parameter :: n=100 > real, dimension(n) :: my_array > > end > !************ Here, n is an integer with the parameter attribute, which may be used as an actual argument for any external or module routine which doesn't try to modify the associated dummy. > but when in a subroutine > > !************ > subroutine my_subroutine(n,array) > integer, intent(in) :: n > real, dimension(n), intent(inout) :: array > <snip some code> > > end subroutine my_subroutine > !************ Here, n is a dummy argument which just happens to have the same name as the n in the main program, but which isn't the same thing. Because this n is intent(in), the compiler will not allow it to be modified, so it is legal to use the n in the main program as the actual argument corresponding to this dummy argument when my_subroutine is called. > e.g. where did the "parameter" go ? Uh, nowhere. n is still a parameter in the main program. > Shouldn't parameter keyword be used every time we wish to, > for example, declare an array ? Not at all.
From: Craig Powers on 19 May 2010 18:10 Craig Powers wrote: > ivan martin wrote: >> Maybe a naive question, but why do we need when in main program >> !************ >> integer, parameter :: n=100 >> real, dimension(n) :: my_array >> >> end >> !************ > > Here, n is an integer with the parameter attribute, which may be used as > an actual argument for any external or module routine which doesn't try > to modify the associated dummy. > >> but when in a subroutine >> >> !************ >> subroutine my_subroutine(n,array) >> integer, intent(in) :: n >> real, dimension(n), intent(inout) :: array >> <snip some code> >> >> end subroutine my_subroutine >> !************ > > Here, n is a dummy argument which just happens to have the same name as > the n in the main program, but which isn't the same thing. Because this > n is intent(in), the compiler will not allow it to be modified, so it is > legal to use the n in the main program as the actual argument > corresponding to this dummy argument when my_subroutine is called. > >> e.g. where did the "parameter" go ? > > Uh, nowhere. n is still a parameter in the main program. > >> Shouldn't parameter keyword be used every time we wish to, >> for example, declare an array ? > > Not at all. To expand on this, it occurs to me that you may also be confused by array and my_array. my_array is a real with rank 1 and size n (main program n), fixed at compile time, cannot be resized. array is an array dummy argument with rank 1 and AT LEAST n elements; something called sequence association applies any time my_subroutine is called, and regardless of what the actual array is that is associated with the dummy named "array", the first n (my_subroutine n) elements of the actual array will be accessed through that dummy in my_subroutine. Which is to say, things are different for a dummy argument vs. a variable, which seems to be the root of most of your concerns.
From: Richard Maine on 19 May 2010 18:25
Craig Powers <craig.powers(a)invalid.invalid> wrote: > ivan martin wrote: > > Shouldn't parameter keyword be used every time we wish to, > > for example, declare an array ? > > Not at all. In particular, although you *CAN* use parameters for such purposes, you don't generaly want to. You could make a parameter n in your subroutine if you wanted instead of passing it as an argument. Do note the "instead of". It can't be both a parameter and a dummy argument; one or the other. They are very different. A parameter is a named constant. A dummy argument is a variable and gets the value of whatever is passed to it. If you use a parameter for the array size in the subroutine, then that array size is fixed for the entire program. In order to change it, you have to change the value of the parameter and recompile. For some subroutines, that is fine. But other subroutines need to be able to handle arrays of different sizes. Think about a trivial case such as a subroutine to add two arrays. (One wouldn't normally write that particular subroutine because the language does it for you, but is a simple example). If you wrote it with parameters for the array dimensions, you would only be able to add one particular size of array in any run of the program. To be able to add two different sizes of array, you would need two different subroutines. That would be... awkward... to say the least. If you use a dummy argument instead of a parameter, then you can have one subroutine to handle any size of array. Or, in Fortran 90 or later (and I see that the code uses other f90 features anyway), one might consider using assumed-shape dummy arrays. Then the array size information is passed for you. That makes for simpler argument lists and helps avoid a large class of common programming errors related to having the dummy argument declaration inconsistent with the actual argument. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |