代码之家  ›  专栏  ›  技术社区  ›  Ross

传递时字符串数组无效

  •  2
  • Ross  · 技术社区  · 6 年前

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

    ! -- 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
    

    但是,Intel18.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 回复  |  直到 6 年前
        1
  •  3
  •   francescalus    6 年前

    您的程序与IFORT 18.0.3的预期工作一致。

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

    问题似乎是

    str_array = 'abc'
    

    在这里, str_array 应该首先取消分配,因为右侧是一个表达式,其长度参数与左侧不同。然后将其分配为长度为3(右侧长度)和形状的字符 [2] 如前所述(右侧为标量)。这确实发生了,正如我们所看到的 SIZE(str_array) LEN(str_array) . 不过,后来当把它用作实际的论点时,会有点不对劲。

    有几种方法可以解决18.0.1中的问题:

    • 把假论点 value 属性;
    • str_array = ['abc','abc'] (不需要以前的分配);
    • str_array(:) = 'abc' (如果你不想重新分配)。

    其他许多可能是可用的,具体取决于您需要什么。不过,如果可以的话,请将编译器升级到最新版本。