Fortran中的BLOCK有什么意义?

And*_*rej 6 fortran

我正在看一些代码,有这样的:

BLOCK

...lines of code...

END BLOCK
Run Code Online (Sandbox Code Playgroud)

目的是BLOCK什么?我试图谷歌它,但我发现的只是一些东西BLOCK DATACOMMON块.我不确定他们是否相关.

fra*_*lus 8

从Fortran 2008标准:

BLOCK构造是一个可执行的构造,可以包含声明.

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

因此,主要用途是"包含声明".

作为范围单位,我们有类似的东西

integer i
block
  integer j ! A local integer
  integer i ! Another i
  save i    ! ... which can even be SAVEd
end block
Run Code Online (Sandbox Code Playgroud)

它提供了声明的位置:

! ... lots of code
block
  integer something
  read *, something
end block
! ... lots more code
Run Code Online (Sandbox Code Playgroud)

这些作用域允许自动对象:

integer i
i = 5
block
  real x(i)
end block
Run Code Online (Sandbox Code Playgroud)

作为可执行构造,它们还具有有用的流控制:

this_block: block
  if (something) exit this_block
  ! ... lots of code
end block
Run Code Online (Sandbox Code Playgroud)

他们还有最终控制权:

type(t) x
block
  type(t) y
end block ! y is finalized
end  ! x is not finalized
Run Code Online (Sandbox Code Playgroud)

for final xyfinalizable类型.

哦,让我们不要忘记你如何用隐式打字来混淆人们.

  • 好话“哦,我们不要忘记如何用隐式类型来迷惑人们。” (2认同)

kva*_*our 5

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

示例 1:

IF (swapxy) THEN
  BLOCK
    REAL (KIND (x)) tmp
    tmp = x
    x = y
    y = tmp
  END BLOCK
END IF
Run Code Online (Sandbox Code Playgroud)

这里变量tmp是在本地定义的,以帮助交换两个变量。在块外部,如果变量tmp是在块外部定义的,则该变量是未知的或返回其原始形式(参见下一个示例)。

示例 2:

F = 254E-2
BLOCK
  REAL F
  F = 39.37
END BLOCK
! F is still equal to 254E-2.
Run Code Online (Sandbox Code Playgroud)

该变量F在块本地重新定义,但在块之外没有任何影响。

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


use*_*492 5

我已经编写了一些有趣的例子.如果要在子程序的同一实例中调用assumed length function不同的内容lengths,该怎么办?你需要一个specification statement告诉编译器你想要的长度,所以一个BLOCK构造可以为你做这个

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
Run Code Online (Sandbox Code Playgroud)

输出gfortran:

III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
Run Code Online (Sandbox Code Playgroud)

或者怎么样,当你需要适当KINDREAL literal?这需要a named constantKIND可能在specification statements另一个MODULE中给出,甚至可以作为一个给出expression.在这种情况下,您可以尝试named constant使用其值来定义a expression,但如果选择了一个不幸的选择,该名称可能会覆盖另一个host associated名称.一个BLOCK构造使一切正常:

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
Run Code Online (Sandbox Code Playgroud)

输出gfortran:

0.729735242E-02
0.72973525663999998E-002
Run Code Online (Sandbox Code Playgroud)

它可能会非常棘手得到Fortran pointerC string,因为没有语法讲C_F_POINTER的什么lengthtargetdeferred length pointer应该是.BLOCK救援!

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
Run Code Online (Sandbox Code Playgroud)

输出gfortran:

12 Hello, world
Run Code Online (Sandbox Code Playgroud)

更不用说a named BLOCK construct给了我们一个labelspaghetti code起来:

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
Run Code Online (Sandbox Code Playgroud)

输出gfortran:

-1 is too small
12! = 479001600
13 is too big
Run Code Online (Sandbox Code Playgroud)