2011-09-30 105 views
18

我有C++/C混合代碼,我建立在奇怪的錯誤()我最近遇到

一)VISUAL C++ 2010速成(免費版)在Win-7的32倍。

b)安裝在Windows-7家庭高級版x32上的Cygwin/Gcc環境。的gcc版本3.4.4(cygming特殊,GDC 0.12,使用DMD 0.125)

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

我有一個代碼,如下(及其對我的用戶定義的類的成員函數),其計算傳遞的對象的絕對值myhalf-這是可以正常使用根據需要在MS

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

- 視覺C++ 2010 ABS -ve號的()被送回正確地說+ ve nos具有相同的值。 奇怪的是,當我在b)Cygwin/gcc環境&上構建此代碼c)上面提到的Linux-gcc 4.4.3,我得到垃圾輸出。於是解僱了GDB和辛勤的汗水和「二進制搜索方法」中的代碼後,決定在那裏開始出問題了,我打了這段代碼如上圖所示:

tmp = abs(a.value); 

這是奇怪的下行爲Cygwin的/海灣合作委員會。

-ve數字abs()返回0(零)。 WTF?

然後作爲一個替代,避免調用ABS()從STDLIB,並編碼爲低於我自己的腹肌:

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; 
} 

這工作得很好上的cygwin/GCC &被作爲期望的linux-gcc和輸出,當然,它在MS-Visual C++ 2010上運行良好。

這是我使用的cygwin/gcc和linux-gcc版本的整個Makefile。只是如果有人supspects有鬼有: -

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) 

1]這是怎麼回事?這個奇怪的bug的根源是什麼?

2]我使用一些舊版本的gcc在cygwin上有這個問題作爲已知的bug或什麼?

3]這個函數float abs(float)是否已知被棄用,或者是否有更新版本取代它?

任何指針都很有用。

+2

如果你創建了一個小型測試用例,這樣每個人都可以拿到這個代碼片段,不加修改地編譯,然後親自查看你的意思。 – PlasmaHH

+4

'abs()'函數通常會返回一個'int',並將其分配給一個'float'。你確定這不是你問題的根源嗎? – larsks

+1

你有'fabs'的相同行爲嗎? – littleadv

回答

27

math.h具有abs的C版本,其在ints上運行。對於C++過載使用<cmath>,對於C浮點版本使用fabs()

+1

是的,我看到我包括math.h(不推薦使用包含C庫中的C庫代碼,我的不好)將嘗試cmath.h或cstdlib,作爲還建議Mark.B – goldenmean

+3

@goldenmean:cmath,而不是cmath.h。標準C++頭文件沒有擴展名 – PlasmaHH

+0

@PlasmaHH - Yean,對不起。它的。 – goldenmean

11

首先,abs()需要並返回int。你應該使用fabs(),它接受並返回一個浮點值。現在

,該abs()你結束了通話實際上是一個GCC built-in function,它返回一個int,但顯然接受float參數,在這種情況下返回0

+1

它將實際將'float'轉換爲'int'並截斷該值。這是0.001被截斷爲0,1.001被截斷爲1等。 –

7

幾乎可以肯定發生了什麼事情是,在你的MSVC情況下,它正在撿起C++ abs浮點重載(可能由於某種原因將其帶入全局命名空間)。然後在g ++中,它不是拾取C++版本(不是隱式地導入到全局名稱空間),而是C版本,它返回一個int,然後將輸出截斷爲零。

如果你#include <cmath>和使用std::abs它應該適用於所有的平臺。