Fortran中块的意义是什么?

Fortran中块的意义是什么?,fortran,Fortran,我正在查看一些代码,其中有: BLOCK ...lines of code... END BLOCK 块的作用是什么?我试着用谷歌搜索它,但我只找到了一些关于块数据和普通块的东西。我不确定它们是否相关。块构造允许您声明实体,如块本地已知但对块外的任何变量没有影响的变量、类型、外部过程等 例1: IF (swapxy) THEN BLOCK REAL (KIND (x)) tmp tmp = x x = y y = tmp END BLOCK END

我正在查看一些代码,其中有:

BLOCK

...lines of code...

END BLOCK

块的作用是什么?我试着用谷歌搜索它,但我只找到了一些关于
块数据
普通
块的东西。我不确定它们是否相关。

构造允许您声明实体,如块本地已知但对块外的任何变量没有影响的变量、类型、外部过程等

例1:

IF (swapxy) THEN
  BLOCK
    REAL (KIND (x)) tmp
    tmp = x
    x = y
    y = tmp
  END BLOCK
END IF
这里,变量
tmp
是本地定义的,用于帮助交换两个变量。在块外部,变量
tmp
未知,如果在块外部定义,则返回其原始形式(参见下一示例)

例2:

F = 254E-2
BLOCK
  REAL F
  F = 39.37
END BLOCK
! F is still equal to 254E-2.
变量
F
在块的局部重新定义,但在块之外没有影响


这些类型的块用于使代码更可读、更容易理解,因为您不需要查看整个子程序来了解本地定义的实体是什么。此外,编译器知道这些实体是本地定义的,因此可能会进行更多优化。

来自Fortran 2008标准:

块构造是可以包含声明的可执行构造

它与公共块或块数据程序单元无关

因此,主要用途是“包含声明”

作为范围界定单位,我们有如下内容

integer i
block
  integer j ! A local integer
  integer i ! Another i
  save i    ! ... which can even be SAVEd
end block
它提供声明的位置:

! ... lots of code
block
  integer something
  read *, something
end block
! ... lots more code
这些范围块允许:

作为可执行结构,它们还具有有用的功能:

它们还具有终结控制:

type(t) x
block
  type(t) y
end block ! y is finalized
end  ! x is not finalized
用于可终结类型的
x
y


哦,别忘了隐式键入是如何把人搞糊涂的。

我又写了几个有趣的例子。如果要在同一子程序实例中调用具有不同
长度的
假定长度函数
,该怎么办?您需要一个
规范语句
来告诉编译器您想要的长度,因此
构造可以为您做到这一点

function F(x)
   implicit none
   character(*) F
   character x(:)
   integer i
   do i = 1, len(F)
      F(i:i) = x(1)
   end do
end function F

program blox1
   implicit none
   integer i
   character c
   do i = 1, 7
      c = achar(65+modulo(i**4+6*i**2+1,26))
      block
         character(2*i+1), external :: F
         call blox1a(F)
      end block
   end do
   contains
      subroutine blox1a(F)
         interface
            function F(x)
               import
               implicit none
               character(2*i+1) F
               character x(:)
            end function F
         end interface
         write(*,'(a)') F([c])
      end subroutine blox1a
end program blox1
使用
gfortran
输出:

III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
0.729735242E-02
0.72973525663999998E-002
12 Hello, world
-1 is too small
12! = 479001600
13 is too big
或者,当您需要一个真正的
文本
时,如何选择合适的
种类
?这需要一个
命名常量
种类
可以在另一个
模块
规范语句
中给出,甚至可以作为
表达式
给出。在这种情况下,您可以尝试使用该
表达式的值定义一个
命名常量
,但如果做出了一个不吉利的选择,该名称可能会覆盖另一个与
主机关联的
名称。一个
构造使一切正常:

module mytypes
   use ISO_FORTRAN_ENV
   implicit none
   type T(KIND)
      integer, kind :: KIND
      real(KIND) x
   end type T
   interface assignment(=)
      module procedure assign8, assign4
   end interface assignment(=)
   contains
      subroutine assign8(x,y)
         real(REAL64), intent(in) :: y
         type(T(kind(y))), intent(out) :: x
         x%x = y
      end subroutine assign8
      subroutine assign4(x,y)
         real(REAL32), intent(in) :: y
         type(T(kind(y))), intent(out) :: x
         x%x = y
      end subroutine assign4
end module mytypes

program blox2
   use mytypes
   implicit none
   type(T(REAL32)) x
BLOCK
!   integer, parameter :: rk = x%KIND ! Not allowed
   integer, parameter :: rk = kind(x%x)
   x = 0.0072973525664_rk
   write(*,'(g0)') x%x
END BLOCK    -1 is too small
12! = 479001600
13 is too big
BLOCK
   type(T(REAL64)) x
BLOCK
!   integer, parameter :: rk = x%KIND ! Not allowed
   integer, parameter :: rk = kind(x%x)
   x = 0.0072973525664_rk
   write(*,'(g0)') x%x
END BLOCK
END BLOCK
end program blox2
使用
gfortran
输出:

III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
0.729735242E-02
0.72973525663999998E-002
12 Hello, world
-1 is too small
12! = 479001600
13 is too big
Fortran指针
获取到
C字符串
可能很棘手,因为没有语法告诉
C\u F\u指针
延迟长度指针的
目标
长度应该是多少<代码>封锁
救援

program blox3
   use ISO_C_BINDING
   implicit none
   character(len=:,kind=C_CHAR), allocatable, target :: x
   type(C_PTR) c_hello
   integer(C_INTPTR_T) address
   character(kind=C_CHAR), pointer :: nul_address
   character(len=:,kind=C_CHAR), pointer :: f_hello
   integer i

   x = 'Hello, world'//achar(0)
   c_hello = C_LOC(x(1:1))
   address = transfer(c_hello,address)
   i = 0
   do
      call C_F_POINTER(transfer(address+i,C_NULL_PTR),nul_address)
      if(nul_address == C_NULL_CHAR) exit
      i = i+1
   end do
BLOCK
   character(len=i,kind=C_CHAR), pointer :: temp
   call C_F_POINTER(c_hello,temp)
   f_hello => temp
END BLOCK
write(*,'(i0,1x,a)') len(f_hello), f_hello
end program blox3
使用
gfortran
输出:

III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
0.729735242E-02
0.72973525663999998E-002
12 Hello, world
-1 is too small
12! = 479001600
13 is too big
更不用说
命名块构造
为我们提供了一个
标签
,将我们的
意大利面代码
挂在:

program blox4
   implicit none
   integer i
   integer j(3)
   integer k

   j = [-1,12,13]
do i = 1, size(j)
factorial: BLOCK
   if(j(i) < 0) then
      write(*,'(*(g0))') j(i),' is too small'
      EXIT factorial
   end if
   if(j(i) > 12) then
      write(*,'(*(g0))') j(i),' is too big'
      EXIT factorial
   end if
   write(*,'(*(g0))') j(i),'! = ',product([(k,k=1,j(i))])
END BLOCK factorial
end do
end program blox4

?顺便说一句,对于谷歌搜索,您可以使用
-
排除一些单词,例如
fortran BLOCK-DATA
。很好的评论“哦,别忘了隐式键入会让人困惑。”@ripero感谢您的阅读和建议编辑。但是,在本例中,“common”和“block data”是在自然语言意义上使用的(参见Fortran标准文档中编写的),而不是作为Fortran语句使用的(这确实会使用代码片段标记)。很抱歉编辑错误。顺便问一下,您能否澄清一下,在终结控制示例中,
x
end块
之后的
end
语句中没有终结的原因?我知道在
end块
中,只有在块内声明的变量(如
y
)才会最终确定,因此
x
不会在那里最终确定,但我希望在到达
end
语句后,
x
会最终确定。@ripero,这不是问题。关于
x
尚未定稿,Fortran就是这样定义的。在F2008中,您可以在4.5.6.4中看到一个明确的语句。@francescalus:好的,我在4.5.6.3中停止了阅读。因此,在您的示例中,
end
是一个
end程序
,但如果它是一个
end函数
end子例程
,那么
x
将最终确定(如果它不是一个伪参数、函数结果或
保存
d)?@francescalus有什么问题
ifort
gfortran
都警告使用过时的
假定长度字符函数
,但如果未删除该函数,则该函数并非无效。Fortran 2008
标准检查生效时,两个编译器是否都缺少问题?因为您使用接口块,因此给定的外部函数的特征必须与函数定义的特征一致。在本例中,定义的函数假定了长度字符函数结果,但接口块说明了不同的内容。现在,如果你用
字符(2*i+1)F
来代替…@francescalus显然我们是通过不同的有色眼镜来看待世界的,所以我们可能不得不再次同意不同意。然而,我戴着你的光学辅助工具做了一次编辑。希望你喜欢:)我的意思是(评论,尤其是在电车上键入的评论,对这种级别的讨论来说不是最好的),那就是
block;字符(2*i+1)F;写(*,‘(a)’F(c);结束块
会起作用。希望这(稍微)更清楚。@francescalus,但这与我的编辑无关,因为我的编辑需要显式的界面。