代码之家  ›  专栏  ›  技术社区  ›  DevSolar

检测宏的使用?(厄尔诺)

  •  9
  • DevSolar  · 技术社区  · 15 年前

    这是非常具体的,有点难以解释,而且很可能是不可能的,但现在开始。

    <errno.h> . (我的爱好项目是实施一项标准 图书馆。)

    中堂的方式是:

    // in <errno.h>
    extern int errno;
    
    // in some .c file
    int errno = 0;
    

    总是 必须在执行后查询FPU状态才能设置 errno 视情况而定。这会使FPU在数学密集型应用程序中暂停。

    这个 C 标准评估 厄尔诺

    int * __errno();
    #define errno *__errno()
    

    这边 只有在实际请求其值时才“设置”:

    // "__errno()" returns the location of the current errno value,
    // the "errno" macro turns it into a value.
    x = errno;
    

    给定库的其余部分中的一些逻辑,仅当调用的最后一个库函数实际上是一个函数时,才需要查询FPU状态 使用 FPU, 厄尔诺 实际上是被要求的 .

    到目前为止,一切都很好。但另一方面也让我头疼:

    errno = 0;
    

    价值 根本不需要。 但是 __errno()

    现在我看不到避免这种情况的方法(即 厄尔诺 宏还是 __errno() 函数的工作方式有所不同,这取决于它们是用于赋值运算符的左侧还是右侧),我几乎满足于接受这一点。

    3 回复  |  直到 9 年前
        1
  •  4
  •   Christoph    15 年前

    这里没有什么好主意,但是很好 errno 允许通过函数调用实现,以使标准库的线程安全实现成为可能。我不认为懒洋洋地查询FPU是个好主意:在这样的情况下,如何避免不一致:

    • 厄尔诺
    • 设置错误标志的浮点操作
    • 得到 厄尔诺
    • 拿旗子

    我应该打电话给你吗 __errno() 是否清除旗帜?

    根据标准,无论是否 必须由数学函数设置,函数值由 math_errhandling math_errhandling & MATH_ERRNO

    数学处理 在编译时。这意味着数学函数不能预先进行静态编译,而必须驻留在头中,这可能是一个好主意,允许没有链接时间优化的编译器内联这些函数。

        2
  •  2
  •   Jonathan Leffler    15 年前

    你这里有一个很好的分析,为什么 errno

    厄尔诺 对于线程安全实现也需要,其中不同的线程具有通过特定于线程的 .

    为了安全起见,您的宏周围可能应该有括号:

    #define errno (*__errno())
    
        3
  •  1
  •   AProgrammer    15 年前

    如果您懒散地检查FPU标志,您将如何在这里获得正确的行为(数学函数的特殊之处在于,它们保证在没有问题时不会修改errno)?

    errno = 0;
    x = acos(y);
    z = <exp>;
    if (errno != 0) {
       /* can't come here even if y is a valid argument but <exp> modified the flags if it didn't call any functions */
    }