我最近遇到的abs()使用中的奇怪错误

gol*_*ean 23 c++ standard-library

我有构建的C++/C混合代码

a)Win-7 x32上的Visual C++ 2010 Express(免费版).

b)安装在Windows-7 Home高级版x32上的Cygwin/Gcc环境.gcc版本3.4.4(cygming special,gdc 0.12,使用dmd 0.125)

c)Ubuntu 10.04 Linux-GCC版本4.4.3(Ubuntu 4.4.3-4ubuntu5)

我有一个代码如下(它是我的用户定义的类的成员函数),它计算传递的对象的绝对值myhalf-

myhalf::myhalfabs(myhalf a)
{
    float tmp;   
    tmp = abs(a.value); //This abs is from math.h :-  float abs(float)
    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

这在MS-Visual C++ 2010中完全按照需要工作.-ve nos的abs()被正确地返回为+ ve nos具有相同的值.奇怪的是,当我在b)Cygwin/gcc环境&c)上面提到的Linux-gcc 4.4.3上构建这个代码时,我得到了垃圾输出.所以激发了gdb,经过大量的汗水和代码上的"二元搜索方法"来决定它出错的地方,我点击了上面这段代码:

tmp = abs(a.value);
Run Code Online (Sandbox Code Playgroud)

这在cygwin/gcc下表现得很奇怪.

对于-ve数字,abs()返回0(零).WTF?

然后作为解决方法,避免从stdlib调用abs(),并编码我自己的abs,如下所示:

myhalf::myhalfabs(myhalf a)
{
    float tmp;
    unsigned int tmp_dbg;
    // tmp = abs(a.value);
    tmp_dbg = *(unsigned int*)(&a.value);
    tmp_dbg = tmp_dbg & 0x7FFFFFFF;
    tmp = *(float*)(&tmp_dbg);

    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

这在cygwin/gcc和linux-gcc上运行良好,并且输出符合要求,当然它在MS-Visual C++ 2010上运行良好.

这是我使用的cygwin/gcc和linux-gcc构建的整个Makefile.如果有人在那里看到可疑的东西: -

OBJS= <all my obj files listed here explicitly>

HEADERS= <my header files here>
CFLAGS= -Wall
LIBS= -lm
LDFLAGS= $(LIBS)

#MDEBUG=1
ifdef MDEBUG
CFLAGS += -fmudflap
LDFLAGS += -fmudflap -lmudflap
endif

myexe:    $(OBJS)
    g++ $(OBJS) $(LDFLAGS) -o myexe

%.o:    %.cpp $(HEADERS) Makefile
    g++ $(CFLAGS) -c $<

clean:
    rm -f myexe $(OBJS)
Run Code Online (Sandbox Code Playgroud)

1]这里发生了什么?这个奇怪的bug的根本原因是什么?

2]我在cygwin上使用了一些旧版本的gcc,这个问题是已知的bug还是什么?

3]这个函数float abs(float)是否已被弃用或者某个更新版本取代它?

任何指针都很有用.

Dav*_*ger 31

math.h其C版本absints 上运行.使用<cmath>的C++重载或使用fabs()为C浮点版本.

  • @goldenmean:cmath,而不是cmath.h.标准c ++标头没有扩展名 (3认同)

Fré*_*idi 14

首先,abs()接受并返回一个int.你应该使用fabs(),它接受并返回一个浮点值.

现在,abs()你最终调用实际上是一个GCC 内置函数,它返回一个int,但显然接受一个float参数并0在这种情况下返回.

  • 它实际上会将 `float` 转换为 `int` 并截断该值。即 0.001 被截断为 0,1.001 被截断为 1,依此类推。 (3认同)

Mar*_*k B 9

几乎可以肯定的是,在你的MSVC情况下,它正在拾取C++ abs浮点重载(由于某种原因可能会被带入全局命名空间).然后在g ++中它没有拿起C++版本(它没有隐式导入到全局命名空间中),而是处理的C版本并返回一个int然后将输出截断为零的版本.

如果您#include <cmath>使用std::abs它应该可以在所有平台上正常工作.