Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Argument type confusion

h-faber
Beginner
2,435 Views
Hi,
I get a strange error message (at least for me) like:
Error: The type of the actual argument differs from the type of the dummy argument. ['ABCDE']

when I have this code:


! somewhere in the declarations:
Interface
CHARACTER(len=80) FUNCTION MYFUNC(MYVAR,FIELD,FVALUE,
+ MYERR)
END FUNCTION MYFUNC
End interface

CHARACTER*(*) ABCDE ! CHARACTER(len=80) ABCDE makes no difference

! later on:
ABCDE = MYFUNC ('ABCDE', FIELD, FVALUE, MYERR)

! and the function goes like:
CHARACTER(len=80) FUNCTION MYFUNC (MYVAR,FIELD,FVALUE,MYERR)
! some declarations
CHARACTER(len=80) :: MYVAR
CHARACTER(len=80) :: STRING
! something more
MYFUNC = STRING
RETURN
END FUNCTION MYFUNC


IMO all the variables have the correct type, especially ABCDE when being submitted into the function call. Where do I go wrong?
0 Kudos
17 Replies
Steven_L_Intel1
Employee
2,435 Views
'ABCDE' is CHARACTER*5, not CHARACTER*80. You probably wanted CHARACTER(*) instead. If you had assigned back into MYVAR, you would have corrupted memory.
0 Kudos
h-faber
Beginner
2,435 Views


sblionel wrote:
'ABCDE' is CHARACTER*5, not CHARACTER*80. You probably wanted CHARACTER(*) instead. If you had assigned back into MYVAR, you would have corrupted memory.




Unfortunately the compiler complains when I try to define

Interface
CHARACTER(len=*) FUNCTION MYFUNC(...)
END FUNCTION MYFUNC
End interface

and says no asterisk is allowed there. As I want to use MYFUNC not only with CHARACTER*5, which number do I have to take?
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
That's not what I suggested. The issue is with the argument(s), not the function itself.
0 Kudos
h-faber
Beginner
2,435 Views
Sorry for annoying you but I am new to Fortran and I do not get this problem solved - maybe I should go back to Java. =:-|
No matter what I change, I still get the same error. If I change the declaration to CHARACTER*5 :: ABCDE or CHARACTER(len=5) :: ABCDE
What am I doing wrong, what do I misunderstand? :-(
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
You are passing a five-character value, 'ABCDE', but have declared the argument receiving it, MYVAR, as 80-characters. This is a mismatch.

What you want is something like this:

CHARACTER(len=80) FUNCTION MYFUNC (MYVAR,FIELD,FVALUE,MYERR)
! some declarations
CHARACTER(len=*) :: MYVAR
CHARACTER(len=*) :: STRING
! something more
MYFUNC = STRING
RETURN
END FUNCTION MYFUNC

This tells the compiler to use the length of the value that was passed, rather than a fixed 80.

It is not clear to me how you are using this function. It will always return an 80-character string, blank padded. Is that what you want? The code you showed for declaring variable ABCDE (not the literal 'ABCDE') can't be CHARACTER(*) - it has to have a fixed length.

Message Edited by sblionel on 03-21-2005 11:22 AM

0 Kudos
h-faber
Beginner
2,435 Views
Of course a fixed return value is not the best solution. But what can be done, when

CHARACTER(len=*) FUNCTION MYFUNC (MYVAR,FIELD,FVALUE,MYERR)
...

is not allowed?
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
What exactly are you trying to accomplish? What does the function do?
0 Kudos
h-faber
Beginner
2,435 Views
The function just looks up some Character/String if it is contained in an array and returns a number which depends to the string in the array. Like looking up a value in a table.
Table e.g.:
1-AERR
2-BBD
3-CHD
4-CDEFG
5-KLABUM

So if CDEFG shall be looked up, the return value as String is "4" and so on. But it is not my task to rewrite this function but to get the original code to work in Intel Frotran Compiler 8.1... :o At the moment I have the choice between two error messages, but of course I have to get rid of them. Unfortunately I don't know how.
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
Ok - there are two problems in the code you showed in your original post. The first is that the INTERFACE block does not declare the arguments. The second is that you have character arguments with explicit lengths where they really should be (*). So what you want is something like this:

Interface
CHARACTER(len=80) FUNCTION MYFUNC(MYVAR,FIELD,FVALUE,
+ MYERR)
CHARACTER(len=*) MYVAR, FIELD
INTEGER FVALUE, MYERR ! I didn't know what these really were
END FUNCTION MYFUNC
End interface

then the actual function would have the same declarations.

There isn't really a problem with MYFUNC returning CHARACTER(80). If you knew that the length was always 2 or 1, you could make it CHARACTER(2).
0 Kudos
h-faber
Beginner
2,435 Views
Maybe I am stupid, maybe I just do not understand how the variable declarations, parameters and return values work. Maybe I am blind, anyway I still couldn't fiddle out to get this code to work.

Currently I have this:

program CharString
implicit none
CHARACTER(len=80) VAR1
CALL MyFunc(Var1)
end program CharString

SUBROUTINE MyFunc(Var1)
implicit none
CHARACTER*(*) VAR1

CHARACTER(len=*) :: CALLER
! CHARACTER CALLER*(*)
CHARACTER VAL2(*)*(*)
CHARACTER VAL3(*)*(*)
INTEGER VAL4(*)
!------------------------
Interface
CHARACTER(len=80) FUNCTION CHANGE(VAL1,VAL2,VAL3,VAL4)
CHARACTER(len=*) VAL1
INTEGER VAL4(*)
CHARACTER VAL2(*)*(*)
CHARACTER VAL3(*)*(*)
! CHARACTER VAL1(*)*(*)
END FUNCTION CHANGE
End interface
!------------------------

CALLER = CHANGE('CALLER', VAL2, VAL3, VAL4)
END SUBROUTINE

!------------------------
!------------------------
CHARACTER(len=80) FUNCTION CHANGE (VAL1,VAL2,VAL3,VAL4)
INTEGER VAL4(*)
INTEGER COUNTER
CHARACTER VAL2(*)*(*)
CHARACTER VAL3(*)*(*)
! CHARACTER VAL1*(*)
CHARACTER(len=*) :: VAL1
CHARACTER(len=*) :: STRING

COUNTER = 1

DO 55 I = 1, 999
IF (VAL2(COUNTER) .EQ. ' ') GOTO 66
IF (VAL2(COUNTER) .EQ. VAL1) THEN
STRING = VAL3(COUNTER)

CALL CLEFT (STRING)
CHANGE = STRING
VAL4(COUNTER) = 0
GOTO 99
END IF
COUNTER = COUNTER + 1
55 CONTINUE
66 CONTINUE

CHANGE =' '
GOTO 99
77 VAL4(COUNTER) = 77
CHANGE =' '

99 RETURN
END FUNCTION CHANGE
!------------------------

And what I get is first of all (besides several others):
Error: This passed length character name has been used in an invalid context. [CALLER] indicated for line #11 within the subroutine in the declaration part:
CHARACTER(len=*) :: CALLER

In which context and why? And what has to be changed so that it works?
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
It would seem that you need to learn a bit more about the Fortran language. I can't really tell what your program wants to do, but I'll make some observations that may be helpful.

When you have a declaration such as:

INTEGER VAL4(*)

that says that VAL4 is an integer array whose lower bound is 1 and whose upper bound is unspecified. An upper bound of * is allowed only inside routines for its formal arguments.

CHARACTER VAL2(*)*(*)

means that VAL2 is an array of character strings. The upper bound of the array is unspecified and the length of each array element (all the same) is passed in by the caller to the routine (this is done by the compiler.) Again, this is valid for arguments only. In MyFunc, CALLER, VAL2, VAL3 and VAL4 are local variables, not arguments, so may not have (*) array bounds or (*) character lengths.

Your declaration of STRING is invalid because (len=*), which is the same as (*) after CHARACTER, is allowed only for arguments.

When you say something like:

STRING = VAL3(COUNTER)

You are assigning to STRING an array element from VAL3.

What did your original code look like before you changed it?
0 Kudos
h-faber
Beginner
2,435 Views
OK, this is the original code (any code tags available here btw?):

SUBROUTINE MYFUNC (VAR1, VAR2, VAR3, VAR4, Z1,Z2, MN,
+ VAR5, VAR6, VAR7, FHLVAR)

CHARACTER*(*) VAR1
CHARACTER*(*) VAR2
INTEGER VAR3
CHARACTER*(*) VAR4
CHARACTER*(*) VAR5
! etc.

CALL ZSLES (VAR6, FNAME, FVALUE, IERR)
IF (IERR .NE. 0) GOTO 888

VAR1 = CHANGE ('VAR1', FNAME, FVALUE, IUMERR)
CALL ZSCHEC (FNAME, FVALUE, IUMERR, ISTAT)
IF (ISTAT .NE. 0) GOTO 999
! etc.
CHARACTER*(*) FUNCTION CHANGE (VARNAME,FNAME,FVALUE,IUMERR)
INTEGER IUMERR(*)
INTEGER ZCOUNT
CHARACTER FNAME(*)*(*)
CHARACTER FVALUE(*)*(*)
CHARACTER VARNAME*(*)
CHARACTER STRING*80

ZCOUNT = 1
DO 55 I = 1, 999
IF (FNAME(ZCOUNT) .EQ. ' ') GOTO 66
IF (FNAME(ZCOUNT) .EQ. VARNAME) THEN
STRING = FVALUE(ZCOUNT)
CALL CLEFT (STRING)
CHANGE = STRING
IUMERR(ZCOUNT) = 0
GOTO 99
END IF
ZCOUNT = ZCOUNT + 1
55 CONTINUE
66 CONTINUE
CHANGE =' '
GOTO 99
77 IUMERR(ZCOUNT) = 77
CHANGE =' '

99 RETURN
END

My primary task is to get this Fortran 77 / VMS code to compile with Intel 8.1.
I thought to have changed this code above due to the hints I got here so that it should work. Maybe I misunderstood, maybe some translation problems English-German produced some trouble.
Consider me a despoiled Java programmer ;) who has not been confronted with such variable declaration problems before.
If I understand it correctly, (one of) my problem(s) is
CHARACTER*(*) VAR1 which can not be translated for Intel 8.1 because it needs a number, not asterisk for unknown size, right?
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
Intel Fortran accepts all valid Fortran 77 code, and allows for CHARACTER(*) in the places it is normally allowed. But it does diagnose some errors that the VAX compiler did not. There's not enough of the program here for me to advise you as to what needs to change. You've left out declarations of the variables passed to routine CHANGE.

As for code tags - if you're using MSIE, there's a code button that lets you insert formatted code. Unfortunately this doesn't work in Firefox or some other browsers. I hope that will change soon.
0 Kudos
h-faber
Beginner
2,435 Views


sblionel wrote:
Intel Fortran accepts all valid Fortran 77 code, and allows for CHARACTER(*) in the places it is normally allowed. But it does diagnose some errors that the VAX compiler did not. There's not enough of the program here for me to advise you as to what needs to change. You've left out declarations of the variables passed to routine CHANGE.



To be honest, I didn't leave out the variables. They are not declared in the MYFUNC subroutine head nor in any global context. But they are used anyway - another suspicious issue I do not understand. Ah damn it, just found them in an included file. =:-|
CHARACTER*8 FNAME(60)
CHARACTER*40 FVALUE(60)
INTEGER*4 IUMERR(60)
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
Ok - with those lines added, the only complaint I get from Intel Fortran is that CHANGE has not been declared as CHARACTER in the caller. If I added the line:

CHARACTER*80 CHANGE

to the declarations in MYFUNC, it compiled fine. What are you seeing?
0 Kudos
h-faber
Beginner
2,435 Views


sblionel wrote:
Ok - with those lines added, the only complaint I get from Intel Fortran is that CHANGE has not been declared as CHARACTER in the caller. If I added the line:

CHARACTER*80 CHANGE

to the declarations in MYFUNC, it compiled fine. What are you seeing?




Well...what can I say...finally works here too. *pretending some innocence by whistling some notes*
Thanks for pointing me to the error for which I deserve the "fool of the week"... ;-)
It was the missing declarations you mentioned recently which made me search for the reason why the compiler couldn't find the include file - it was in the wrong directory. And because it couldn't be found right at the start I just commented the include line out in the very beginning. :-o
Mea culpa... ;-)
0 Kudos
Steven_L_Intel1
Employee
2,435 Views
I'm glad to hear that it's worked out.
0 Kudos
Reply