检查是否定义了内部变量

时间:2014-06-25 00:58:34

标签: fortran preprocessor intrinsics

Fortran标准不断发展,并且随着新的内在变量的引入,编译器会在一段时间之后选择它们。一个例子是变量C_PTRDIFF_T

为了使我的代码也可以与旧的编译器兼容,我想定义内部变量,如果它们尚未由编译器本身定义,例如,

program test
  USE ISO_C_BINDING
  Integer, Parameter :: C_PTRDIFF_T = 12
end program

如何在编译器之间实现这种可移植性?

2 个答案:

答案 0 :(得分:2)

尝试编译并运行类似于:

的内容
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTRDIFF_T
IF (C_PTRDIFF_T >= 0) THEN
  PRINT "('Ok')"
ELSE
  PRINT "('Not ok')"
END IF
END

如果编译成功,编译器会知道支持C_PTRDIFF_T的标准。

如果运行程序然后打印Ok(所以C_PTRDIFF_T常量的值是非负的),处理器还支持一个可与相关C类型互操作的整数。

根据此测试,您可以根据需要正确配置您的程序,也许可以为模块选择略有不同的源代码,该模块可以提供ISO_C_BINDING的独立定义或转发C_PTRDIFF_T。

后期标准将新实体添加到内部模块的能力是有时建议在内部模块的USE语句中始终使用ONLY子句的编程样式的原因。

(注意C_PTRDIFF_T是内部模块中的常量,它不是变量也不是内在的。)

答案 1 :(得分:0)

您可以在一个过程中实现此目标,因为USE关联胜过主机关联:

module goodstuf
   implicit none
   interface f
      module procedure f4, f8
   end interface f
   contains
      function f4(x)
         integer(4) f4
         integer(4), intent(in) :: x
         f4 = x**2+1
      end function f4
      function f8(x)
         integer(8) f8
         integer(8), intent(in) :: x
         f8 = x**3-1
      end function f8
end module goodstuf

module user5713492_C_BINDING
   implicit none
!   integer, parameter :: C_PTRDIFF_T = 8
end module user5713492_C_BINDING

module anymod
   use goodstuf
   implicit none
   integer, parameter :: C_PTRDIFF_T = 4
   contains
      subroutine sub
         use user5713492_C_BINDING
         integer(C_PTRDIFF_T) x
         x = 7
         write(*,*) f(x)
      end subroutine sub
end module anymod

program main
   use anymod
   implicit none
   call sub
end program main

在模块50中注释掉C_PTRDIFF_T的定义时,将打印出user5713492_C_BINDING,而在模块342中,则将其注释掉。但是我希望做的是定义一个命名常量,该常量在定义1时具有值C_PTRDIFF_T,而在没有0时具有值。我可以通过使用隐式类型的testSTORAGE_SIZEBIT_SIZE内在函数为命名常量DIM实现此功能,假设默认整数KIND不是INT8。但是,在未定义C_PTRDIFF_T的情况下进行压缩似乎需要某种编译器错误。我使用gfortran进行了尝试,并发现了两个错误,最后一个错误使该错误得以解决,将FSOURCE=自变量压缩为MERGE内部变量。不幸的是,它不适用于ifort。

module goodstuf
   implicit none
   interface f
      module procedure f4, f8
   end interface f
   contains
      function f4(x)
         integer(4) f4
         integer(4), intent(in) :: x
         f4 = x**2+1
      end function f4
      function f8(x)
         integer(8) f8
         integer(8), intent(in) :: x
         f8 = x**3-1
      end function f8
end module goodstuf

module user5713492_C_BINDING
   implicit none
!   integer, parameter :: C_PTRDIFF_T = 8
end module user5713492_C_BINDING

module filter
   use user5713492_C_BINDING
   use ISO_FORTRAN_ENV, only: INT8
   implicit integer(INT8) (C)
   integer, parameter :: PTRDIFF_size = storage_size(C_PTRDIFF_T)
   integer, parameter :: test = dim(1,(PTRDIFF_size-bit_size(1))**2)
   integer, parameter :: MY_PTRDIFF_T = 4
! First test: try to squash PAD= argument to RESHAPE
!   integer, parameter :: array1(test) = reshape([integer(INT8)::],[test],pad=[C_PTRDIFF_T])
!   integer, parameter :: array2(1) = reshape(array1,[1],pad=[MY_PTRDIFF_T])
! Second test: try to squash assignment to zero-length array
!   integer, parameter :: array1(test) = C_PTRDIFF_T
!   integer, parameter :: array2(1) = reshape(array1,[1],pad=[MY_PTRDIFF_T])
! Third test: try to squash zero-length structure constructor
! Fails with gfortran with C_PTRDIFF_T defined. Bug?
!   type T
!      integer array(test)
!   end type T
!   type(T), parameter :: T1 = T(C_PTRDIFF_T)
!   integer, parameter :: array2(1) = reshape(T1%array,[1],pad=[MY_PTRDIFF_T])
! Fourth test: try to squash BOUNDARY= argument to EOSHIFT
! gfortan gives misleading error message with C_PTRDIFF_T undefined.
!   integer, parameter :: array2(1) = eoshift([integer(KIND(C_PTRDIFF_T))::MY_PTRDIFF_T],1,boundary=C_PTRDIFF_T)
! Fifth test: try to squash FSOURCE= argument to MERGE
!!! WORKS WITH gfortran!!!
   integer, parameter :: array2(1) = merge([integer(KIND(C_PTRDIFF_T))::MY_PTRDIFF_T],C_PTRDIFF_T,test==0)
   integer, parameter :: OK_PTRDIFF_T = array2(1)
end module filter

program main
   use goodstuf
   use filter
   implicit none
   integer(OK_PTRDIFF_T) x
   x = 7
   write(*,*) f(x)
end program main