Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C的编译器选项捕获浮点异常_C_Floating Point_Fortran_Scientific Computing - Fatal编程技术网

使用C的编译器选项捕获浮点异常

使用C的编译器选项捕获浮点异常,c,floating-point,fortran,scientific-computing,C,Floating Point,Fortran,Scientific Computing,Gfortran有方便的-ffpe trap编译器选项,但没有类似的选项可用于gcc。我模模糊糊地意识到它们处理异常的方式不同,但这还不足以知道为什么一个人只需启用编译器标志就可以死于FPE,而另一个人则需要包含额外的代码来打开异常;真正的答案在底部 浮点异常由C99中的库代码控制,而不是由编译器标志控制。下面是一个例子: #include <fenv.h> #include <math.h> #include <stdio.h> #define PRINT

Gfortran有方便的
-ffpe trap
编译器选项,但没有类似的选项可用于gcc。我模模糊糊地意识到它们处理异常的方式不同,但这还不足以知道为什么一个人只需启用编译器标志就可以死于FPE,而另一个人则需要包含额外的代码来打开异常;真正的答案在底部

浮点异常由C99中的库代码控制,而不是由编译器标志控制。下面是一个例子:

#include <fenv.h>
#include <math.h>
#include <stdio.h>

#define PRINTEXC(ex, val) printf(#ex ": %s\n", (val & ex) ? "set" : "unset");

double foo(double a, double b) { return sin(a) / b; }

int main()
{
    int e;
    double x;

    feclearexcept(FE_ALL_EXCEPT);

    x = foo(1.2, 3.1);

    e = fetestexcept(FE_ALL_EXCEPT);
    PRINTEXC(FE_DIVBYZERO, e);
    PRINTEXC(FE_INEXACT, e);
    PRINTEXC(FE_INVALID, e);
    PRINTEXC(FE_OVERFLOW, e);
    PRINTEXC(FE_UNDERFLOW, e);

    putchar('\n');

    feclearexcept(FE_ALL_EXCEPT);

    x += foo(1.2, 0.0);

    e = fetestexcept(FE_ALL_EXCEPT);
    PRINTEXC(FE_DIVBYZERO, e);
    PRINTEXC(FE_INEXACT, e);
    PRINTEXC(FE_INVALID, e);
    PRINTEXC(FE_OVERFLOW, e);
    PRINTEXC(FE_UNDERFLOW, e);
    return lrint(x);
}

更新:使用GNU GCC,您可以选择导致浮点异常陷阱并发送信号:

#pragma STDC FENV_ACCESS on

#define _GNU_SOURCE
#include <fenv.h>

int main()
{
#ifdef FE_NOMASK_ENV
    fesetenv(FE_NOMASK_ENV);
#endif

    // ...
}
\pragma STDC FENV_访问
#定义GNU源
#包括
int main()
{
#ifdef FE_NOMASK_ENV
fesetenv(feu NOMASK_ENV);
#恩迪夫
// ...
}

然而,当您收到SIGFPE时,您应该做什么并不完全清楚,因为您无法撤消错误的指令。(请参阅@EricPostpischil对pragma的评论;谢谢!)

我认为这并没有以任何方式回答OP的问题。OP问的是为什么gfortran有FPE标志而gcc没有,而不是C中的FPE标志如何。@KyleKanos:你说得对。我不完全确定我在找什么,但现在我找到了。已更新。访问浮点环境或在非默认浮点控制模式下运行的代码必须使用#pragma STDC FENV_ACCESS on通知实现。否则,该行为未被C标准定义。@KerrekSB:C 2011(N1570)7.6.1,也是在C 1999中。实际上,如果缺少pragma,那么说行为是未定义的就太过分了。默认的FENV_访问状态是实现定义的。如果实现将其定义为“off”,并且缺少pragma,则该标准未定义行为。如果我没记错的话,GCC有一段时间不支持pragma。@KyleKanos说得比我好:为什么我需要使用
feenableexcept
fsetenv
,而不仅仅是编译器标志?注意在Fortran 2003中,人们可以做很多类似于C的事情,包括IEEE异常和舍入模式。但gfortran还不支持。如果使用编译器标志来捕获异常,它可能会干扰这样的代码。