errno值未更新(c ++)

时间:2016-08-07 15:01:16

标签: c++

我是编码新手(目前正在学习c ++,而且我知道一点C)......

正在阅读math.h中的函数,并阅读有关errno ...

的内容

根据我提到的网站: -

  

域错误(输入参数超出了数学定义操作的范围,例如std :: sqrt(-1),std :: log(-1)或std :: acos(2))。如果设置了MATH_ERRNO位,则将EDOM分配给errno。如果设置了MATH_ERREXCEPT位,则引发FE_INVALID。

所以我尝试用这些知识编写一个小程序......

#include <iostream>
#include <cerrno>
#include <cmath>
using namespace std;

int main (void)
{
  errno = 0;
  cout<<"\nWhat I get :-\n";
  cout << "log(-3) = " << log(-3) << "\n"; 
  //shouldn't it do (errno = EDOM) in the above step?
  cout << "errno = " << errno << "\n";
  cout << strerror(errno) << "\n";

  errno = EDOM;
  cout<<"\nWhat I want :-\n";
  cout << "log(-3) = " << log(-3) << "\n";
  cout << "errno = " << errno << "\n";
  cout << strerror(errno) << "\n\n";

  return(0);
}

在输出中我看到errno没有在我的第一个块中更新到EDOM,即使-3不在log()的域中...

输出: -

What I get :-
log(-3) = nan
errno = 0
Undefined error: 0

What I want :-
log(-3) = nan
errno = 33
Numerical argument out of domain

我不明白我在这里失踪的是什么...... Plz帮助......

我正在Mac上的Apple LLVM版本7.3.0(clang-703.0.31)上编译我的代码。

2 个答案:

答案 0 :(得分:2)

#define MATH_ERRNO 1是非法的。您不应重新定义标准库符号。 MATH_ERRNO已经按标准定义为1。

您无法设置实现如何处理错误(除了特定于编译器的开关。请阅读编译器的文档)。你只能检查一下:

if (math_errhandling & MATH_ERRNO)
    std::cout << "Error reporting uses errno\n";
else 
    std::cout << "Error reporting does not use errno\n";

if (math_errhandling & MATH_ERREXCEPT)
    std::cout << "Error reporting uses floating-point exceptions\n";
else 
    std::cout << "Error reporting does not use floating-point exceptions\n";

对于clang,使用/不使用-fmath-errno的相关标记为-fmath-no-errno / errno

discussion on reported bug来看,标准库的Mac实现根本不使用errno。如果你想用它来报告错误,你就不走运了。

答案 1 :(得分:0)

您可以在http://www.cplusplus.com/reference/cmath/math_errhandling/找到数学错误处理的完整示例(在C中) 对于该站点的完整性示例:

#include <stdio.h>      /* printf */
#include <math.h>       /* math_errhandling */
#include <errno.h>      /* errno, EDOM */
#include <fenv.h>       /* feclearexcept, fetestexcept, FE_ALL_EXCEPT, FE_INVALID */
#pragma STDC FENV_ACCESS on

int main () {
  errno = 0;
  if (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT);

  printf ("Error handling: %d",math_errhandling);

  sqrt (-1);
  if (math_errhandling & MATH_ERRNO) {
    if (errno==EDOM) printf("errno set to EDOM\n");
  }
  if (math_errhandling  &MATH_ERREXCEPT) {
    if (fetestexcept(FE_INVALID)) printf("FE_INVALID raised\n");
  }

  return 0;
}