Error: Rank mismatch in argument ‘cars’ at (1) (scalar and rank-1)

With these compiler options, how do I prevent this error and maintain the logic in the program?

-g -Wall -Werror -fmax-errors=1 -fcheck=all

SUBROUTINE TESTING (cars)
CHARACTER cars*(*)
print *,"CARS=", cars(1),cars(2),cars(3)
end 
Program TEST
Character test1 * 10
Character test2 * 30
COMMON /ABC/test1(10)
COMMON /DEF/test2(30)
test1(1)= 'A'
test1(2)= 'B'
test1(3)= 'C'
CALL TESTING (test1)

test2(1)= 'X'
test2(2)= 'Y'
test2(3)= 'Z'
CALL TESTING (test2)
End Program TEST
Error Message:
   13 | CALL TESTING (test1)
      |              1
Error: Rank mismatch in argument ‘cars’ at (1) (scalar and rank-1) [-Werror=argument-mismatch]
f951: all warnings being treated as errors

With some changes seems to work, :slight_smile:

module testing_mod 
  implicit none

  character(len=10) :: test1(10)
  character(len=30) :: test2(30) 

contains
 
   subroutine testing_sub (cars)
      character(*) :: cars(:)
      print *,"CARS=", cars(1),cars(2),cars(3)
   end subroutine testing_sub
  
end module testing_mod
 
program test
  use testing_mod
   
   test1(1)= "A"
   test1(2)= "B"
   test1(3)= "C"
   call testing_sub(test1)
  
   test2(1)= "X"
   test2(2)= "Y"
   test2(3)= "Z"
   call testing_sub(test2)
  
end program test 

``
gfortran -g -Wall -Werror -fmax-errors=1 -fcheck=all rank.f90 -o rank

./rank
 CARS=A         B         C         
 CARS=X                             Y                             Z

What would you do if an “if” statement were added to the subroutine?

SUBROUTINE TESTING (cars)
CHARACTER cars*(*)
print *,"CARS=", cars(1),cars(2),cars(3)
if (cars(1:1).eq.'<') print *,"works"
end 
Program TEST
Character test1 * 10
Character test2 * 30
COMMON /ABC/test1(10)
COMMON /DEF/test2(30)
test1(1)= 'A'
test1(2)= 'B'
test1(3)= 'C'
CALL TESTING (test1)

test2(1)= 'X'
test2(2)= 'Y'
test2(3)= 'Z'
CALL TESTING (test2)
End Program TEST

The if clause requires a scalar logical expression

you could use something like:

do i = 1, n  
  if (cars(i)(1:1) == '<' ) print*, "works"
end do

Maybe it is worth explaining the problem with original source, apparently Fortran 77 standard, as there are several errors in it.

  1. CHARACTER cars*(*) tells the compiler that the dummy argument cars will be an object of type assumed length character scalar, not an array! It is F77 way of modern CHARACTER(LEN=*). Furthermore, the nature of this object is deduced by the compiler only when it finds it in context, here the context is print *,"CARS=",cars(1).... As cars is a scalar, not an array, cars(1) is interpreted as a function call, thus making the cars a dummy procedure!
  2. In the main program, test1 and test2 are defined as arrays (1-dimensional, a.k.a. rank-1) of character elements having the length of 10 and 30, respectively. This is why you get Rank mismatch.. (scalar and rank-1) at CALL TESTING() statement.

So, to keep the old format, you’d have to change the dummy declaration to
CHARACTER*(*) cars(*)
to make it an array of assumed length character elements

To get convinced about the point 1 above regarding the dummy procedure, change (in the original code!) the test1 and test2 in CALL TESTING() to any scalar character value, say "abc" and "def" and compile. You’ll get something like:
Error: Expected a procedure for argument 'cars'

Surely @alozada’s solution is much better, converted to modern Fortran.

An implicit none would be nice. Goes to show how easy it can be to forget.

1 Like

of course, :flushed: . implicit none

How do you get ‘B’, ‘C’, ‘Y’, and ‘Z’ to be output?

SUBROUTINE TESTING (cars)
  CHARACTER cars(*)
  integer n 
  integer i
  n = 3
  do i = 1, n  
    if ((cars(i)(1:1)) /= '<')  print*, cars(i)(1:1)," works"
  end do
end 
Program TEST
  Character test1 * 10
  Character test2 * 30
  COMMON /ABC/test1(10)
  COMMON /DEF/test2(30)
  test1(1)= 'A'
  test1(2)= 'B'
  test1(3)= 'C'
  CALL TESTING (test1)

  test2(1)= 'X'
  test2(2)= 'Y'
  test2(3)= 'Z'
  CALL TESTING (test2)
End Program TEST

— Output —
A works
works
works
X works
works
works

By reading and applying my earlier hint?

As it is now, without the magical *(*) , cars dummy argument is an array of len=1 character elements. And you are sending arrays of len=10 or len=30 elements