区分变量和常量

时间:2016-08-05 06:44:12

标签: fortran

好的,在我开始之前:我知道这真的很糟糕。如果有一个每个人都遵循的设计协议,那我就要求对一个不会发生的情况进行破解。但这是我的问题。

我有一个庞大的Fortran代码库,带有错误报告例程。只有在发生奇怪的事情时才会调用错误报告例程,并且它具有整数输入:ErrorCode。正值表示错误和中止,负值表示警告并继续。

这是我的问题:

有些人已经开始调用错误报告功能:

ErrorCode = -5
call error_report(ErrorCode)
if (ErrorCode /= 0) stop "Hey, you were supposed to reset ErrorCode"

我不知道是否有任何对error_report实际上希望将ErrorCodeerror_report重置为0的调用。我所知道的是call error_report(-5) 的当前实现这样做,我不想改变任何功能。

其他人让自己更轻松:

ErrorCode

目前,在例程中,INTENT未声明任何INTENT(INOUT),只是为了编译代码。但当然这只意味着无论何时以第二种方式调用警告,而不是显示警告并继续工作,程序会出现段错误。

我现在没有时间和权限来正确清理代码(通常我只是将其设置为error_report然后让编译器告诉我需要进行更改的地方。但是这个由于各种原因,目前不是一种选择。)

有没有什么方法可以编写一个满足两个版本的例程print((stats!["reward_listing"]! as? NSDictionary)!) ?程序重载?区分变量和常量的一些方法?什么?

1 个答案:

答案 0 :(得分:3)

这个想法应该适用于任何* nix系统......主要思想是将常量文字作为符号编译到二进制文件中,而变量则不是。 因此,如果您使用ld进行链接,则会在最终位置插入符号_end(对于静态和动态链接)。 这可以(ab)用来检查给定的伪参数在_end之前或之后是否具有地址。如果地址较低,则实际参数为常量,否则为(临时)变量。

然而,这需要一些C代码:

<强> addr.c

int isConstant(int *x){
  extern void *_end;
  if ( (void *)x > (void *)&_end ) {
    return 1; // Variable
  } else {
    return 0; // Constant
  }
}

<强> test.F90

program test
  use,intrinsic :: ISO_C_Binding
  interface
    integer(C_INT) function isConstant(a) bind(C, name="isConstant")
      use,intrinsic :: ISO_C_Binding
      integer(C_INT), intent(in) :: a
    end function
  end interface

  integer :: i
  integer,parameter :: ii=2
  i = 1

  print *,isConstant(i)
  print *,isConstant(1)
  print *,isConstant((i))
  print *,isConstant(ii)

end program

将其编译为

gfortran -Wall -Wextra test.F90 addr.c 

它会给你:

./a.out 
           1
           0
           1
           0

请注意,我没有使用mingw在Windows上测试Windows 。使用风险由您自己承担。

请注意,常量表达式(i)不能按标准定义。但是,它是在运行时创建的,因此不是符号。这在输出中很明显。 但是,在OP的上下文中,我在尝试为其赋值时没有遇到段错误。