传递时字符串数组被取消
String array being nullified when passing
我在传递字符串数组时遇到问题。考虑以下示例代码:
! -- 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
我有几个与此行为相关的问题:
为什么会出现这种情况?我认为这可能与英特尔强制执行 lhs 重新分配有关,但我不确定。添加 -assume norealloc_lhs
没有任何改变。
像这样传递字符串数组的正确语法是什么?我可以用不同的方式声明它并避免这个问题吗?
我可以在这台机器上访问的英特尔版本具有以下行为:
- 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 - 无效
在另一台机器上,我没有任何最新的英特尔:
- ifort (IFORT) 14.0.2 20140120 - 没有失效
- ifort (IFORT) 16.0.0 20150815 - 没有失效
您的程序在 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'
(如果您不想重新分配)。
可能还有许多其他可用的,具体取决于您的需要。不过,如果可以的话,请将您的编译器升级到最新版本。
我在传递字符串数组时遇到问题。考虑以下示例代码:
! -- 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
我有几个与此行为相关的问题:
为什么会出现这种情况?我认为这可能与英特尔强制执行 lhs 重新分配有关,但我不确定。添加
-assume norealloc_lhs
没有任何改变。像这样传递字符串数组的正确语法是什么?我可以用不同的方式声明它并避免这个问题吗?
我可以在这台机器上访问的英特尔版本具有以下行为:
- 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 - 无效
在另一台机器上,我没有任何最新的英特尔:
- ifort (IFORT) 14.0.2 20140120 - 没有失效
- ifort (IFORT) 16.0.0 20150815 - 没有失效
您的程序在 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'
(如果您不想重新分配)。
可能还有许多其他可用的,具体取决于您的需要。不过,如果可以的话,请将您的编译器升级到最新版本。