2016-11-11 82 views
6

考慮下面的代碼:內C - complex.h意外的行爲在不同的操作系統

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <complex.h> 
int main() 
{ 
    complex double aaa = INFINITY + 0*I; 
    printf("%.f + %.f*I\n", creal(aaa), cimag(aaa)); 
    complex double bbb = 1.0/aaa; 
    printf("%.f + %.f*I\n", creal(bbb), cimag(bbb)); 
    return EXIT_SUCCESS; 
} 

gcc -std=gnu99 -lm編譯,我期望輸出

INF + 0 * I

0 + 0 * I

這在Linux上是正確的(在Scienti上測試過使用gcc 4.4.7的fic Linux 6.8,使用gcc 5.3.1的Fedora 23以及使用gcc 4.8.4的Ubuntu 14.04.5)。

然而,在OS X(10.11.5鏗鏘-602.0.53),而不是我得到

INF + 0 * I

囡楠+ * I

它很顯然,叮噹不符合C99標準(見N1256,G.5.1節;嚴格地說,這只是一個推薦的做法,而不是一個標準)。 實際上,clang沒有定義的宏__STDC_IEC_559_COMPLEX__,這是在第2節中介紹的。 G.1。鏗鏘有意做出這種行爲? 更新:經過一些檢查後,我發現我測試的幾個Linux環境沒有定義這個宏,但代碼在那裏仍然正常工作。

目前,我的跨平臺支持的解決方法是檢查宏觀

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <complex.h> 
int main() 
{ 
    complex double aaa = INFINITY + 0*I; 
    printf("%.f + %.f*I\n", creal(aaa), cimag(aaa)); 
    complex double bbb = 1.0/aaa; 
    #ifndef __STDC_IEC_559_COMPLEX__ 
    if(isnan(bbb)) 
    { 
     bbb = 0; //or do some trick that has to do with the problem context 
    } 
    #endif 
    printf("%.f + %.f*I\n", creal(bbb), cimag(bbb)); 

    return EXIT_SUCCESS; 
} 

但我不知道這是否是穩健的...任何建議?

+2

[C標準](http://port70.net/~nsz/c/c11/n1570.html#7.12p4):* INFINITY 擴展爲浮點類型的常量表達式,表示正或無符號無窮大,if可用的;否則就是在翻譯時溢出的浮點類型的正常數。*因此,跨平臺的行爲可能不完全相同...... –

+0

@EugeneSh。 1.在這種情況下,INFINITY可以擴展到正無窮大,這可以通過第一行輸出來檢查,或者在調試器中檢查;在這裏我寫'INFINITY'只是爲了提供一個MWE。你可以寫出像'complex double aaa = 1.0/0.0;'這樣溢出的東西而不改變結論; 3.如果這不起作用是沒有意義的,因爲我已經測試過一個「double」對象(把所有'complex double'替換爲'double',將函數'creal'和'cimag'去掉等)。 –

+0

@LeoFang它是如何在數學上處理的,以及'printf()'代表的可能不是完全相同的東西。也許最好的方法來確定問題是否真的是'clang'或架構是通過使用'gcc'在OSX上編譯它。 – Havenard

回答

1

對於雙重參數,您正在使用%f而不是%lf。這導致了不可預測的行爲,我想。

相關問題