传递时使字符串数组无效

时间:2018-07-25 16:18:02

标签: fortran intel-fortran

我在传递字符串数组时遇到麻烦。考虑以下示例代码:

! -- Module to declare variable
module my_data
   implicit none

   ! -- Declare as deferred-length allocatable array
   character(len=:), dimension(:), allocatable :: str_array
end module my_data

! -- Module to call subroutine
module my_subs
   implicit none

contains
subroutine a(str_array)
   character(len=*), dimension(:), intent(IN) :: str_array
   integer :: i, j
   character :: c

   do i=1,size(str_array)
      do j=1,len_trim(str_array(i))
         c = str_array(i)(j:j)

         ! -- Write i, j, character, and int representation
         write(*,*) 'In call: ', i, j, ' "'//c//'", ichar = ', ichar(c)
      enddo
   enddo
end subroutine a
end module my_subs

! -- Main program
program main
   use my_data, only : str_array
   use my_subs, only : a
   implicit none
   integer, parameter :: strlen = 200
   integer :: N, i, j
   character :: c

   ! -- Size of str array
   N = 2

   ! -- Allocate str_array, syntax from https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/287349
   allocate(character(strlen) :: str_array(N))

   ! -- Set both to the same string
   str_array = 'abc'

   do i=1,size(str_array)
      do j=1,len_trim(str_array(i))
         c = str_array(i)(j:j)

         ! -- Write i, j, character, and int representation
         write(*,*) 'In main: ', i, j, ' "'//c//'", ichar = ', ichar(c)
      enddo
   enddo

   call a(str_array)
end program main

字符串数组被声明为假定长度的元素数组(来自the wiki)。我分配并设置了字符串的值(在此示例中,两个元素都都为abc)。主例程输出有关字符串的完整详细信息,然后调用子例程,该子例程也输出(希望是相同的)完整详细信息。

使用PGI,GCC或Intel 15.0,我得到了我期望的结果:

chaud106@ln0005 [~/Testing] % ifort --version && ifort -check all -warn all main.f90 && ./a.out
ifort (IFORT) 15.0.3 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

 In main:            1           1  "a", ichar =           97
 In main:            1           2  "b", ichar =           98
 In main:            1           3  "c", ichar =           99
 In main:            2           1  "a", ichar =           97
 In main:            2           2  "b", ichar =           98
 In main:            2           3  "c", ichar =           99
 In call:            1           1  "a", ichar =           97
 In call:            1           2  "b", ichar =           98
 In call:            1           3  "c", ichar =           99
 In call:            2           1  "a", ichar =           97
 In call:            2           2  "b", ichar =           98
 In call:            2           3  "c", ichar =           99

但是,Intel 18.0将字符数组的第二个元素(所有3个字符)设置为空字符:

chaud106@ln0005 [~/Testing] % ifort --version && ifort -check all -warn all main.f90 && ./a.out
ifort (IFORT) 18.0.0 20170811
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.

 In main:            1           1  "a", ichar =           97
 In main:            1           2  "b", ichar =           98
 In main:            1           3  "c", ichar =           99
 In main:            2           1  "a", ichar =           97
 In main:            2           2  "b", ichar =           98
 In main:            2           3  "c", ichar =           99
 In call:            1           1  "a", ichar =           97
 In call:            1           2  "b", ichar =           98
 In call:            1           3  "c", ichar =           99
 In call:            2           1  "", ichar =            0
 In call:            2           2  "", ichar =            0
 In call:            2           3  "", ichar =            0

我有与此行为有关的几个问题:

  1. 为什么会这样?我以为这可能与英特尔实施lhs重新分配有关,但我不确定。添加-assume norealloc_lhs并没有任何改变。

  2. 传递这样的字符串数组的正确语法是什么?我可以用不同的方式声明它并避免这个问题吗?

我可以在此计算机上访问的Intel版本具有以下行为:

  • ifort(IFORT)15.0.2 20150121-不作废
  • ifort(IFORT)15.0.3 20150407-不作废
  • ifort(IFORT)16.0.3 20160415-不作废
  • ifort(IFORT)17.0.4 20170411-无效
  • ifort(IFORT)18.0.0 20170811-无效

在另一台计算机上,我没有任何最新的Intel:

  • ifort(IFORT)14.0.2 20140120-不作废
  • ifort(IFORT)16.0.0 20150815-不作废

1 个答案:

答案 0 :(得分:3)

您的程序在ifort 18.0.3中可以正常工作。

我还没有尝试过很多以前的版本,但是我注意到,在固有编译器上,Fortran 2003自动分配成为该编译器中的默认值是17.0.1。

问题线似乎是

str_array = 'abc'

在这里,str_array应该首先被释放,因为右边是一个表达式,其长度参数与左边不同。然后将其分配为长度为3(右侧的长度)和形状为[2]的字符(右侧为标量)。正如SIZE(str_array)LEN(str_array)所见,这确实发生了。不过,将其用作实际参数时,有些事情会出问题。

有一些方法可以解决18.0.1中的此问题:

  • 为虚拟参数赋予value属性;
  • str_array = ['abc','abc'](不需要先前的分配);
  • str_array(:) = 'abc'(如果您不希望重新分配)。

根据您的实际需要,可能还会有许多其他产品。不过,可以的话,将编译器升级到最新版本。