4

次のコードが他の3つと比較してtest4変数に対して異なる出力を生成する理由を誰かが説明できますか? これを gcc バージョン 4.2.1 および 4.5.3 (およびその間の他のバージョン) で確認しました。

明らかな何かが欠けているかもしれませんが、かなり簡単に見えます...

#include <stdio.h>
#include <complex.h>

main()
{
    double complex test1, test2, test3, test4;

    test1 = 81141117.0;
    test2 = 81141117.0 + I * 0;
    test3 = 81141117 + I * 0.0;
    test4 = 81141117 + I * 0;
    printf("%ld + %ld I, %ld + %ld I, ", (long)creal(test1), (long)cimag(test1), (long)creal(test2), (long)cimag(test2));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test3), (long)cimag(test3), (long)creal(test4), (long)cimag(test4));
}

出力:

81141117 + 0 I, 81141117 + 0 I
81141117 + 0 I, 81141120 + 0 I

整数項のみを持つ test4 が、宣言された double ではなく float に昇格され、丸めが行われているようです。

4

1 に答える 1

4

私は Mac OS X 10.7.5 (自家製 GCC) で GCC 4.7.1 をテストし、提供されたシステムと をテストしましたが/usr/bin/gcc/usr/bin/clangそれらはすべてあなたが報告したのと同じ結果を生成します。

複素数の両方の項が整数として表される場合のfloat代わりにへの変換が必要であるというあなたの分析に同意します。doubleC 2011 標準には、次の例が含まれています。

ISO/IEC 9899:2011 §6.7.9 初期化

¶24<complex.h>#include1

int i = 3.5;
double complex c = 5 + 3 * I;

値 3 で i を定義し、値 5 で c を初期化します。0 + i3. 0.

これは、整数式を記述して有効な値を取得できる必要があることを明確に示していますdouble complex(ただし、例は規範的ではありません)。ただし、整数値を に変換するfloat前に に変換する必要があるかどうかについては触れてdoubleいませんが、言語にはそれを自動的に行う場所が他にないため (明らかに強制できます)、意図した解釈である可能性は低いです。

全体として、これは GCC チームに報告できるバグである可能性が高いと思います (これは軽々しく行うべきではありません)。を実行するgcc --helpと、出力は次のメッセージで終了します。

For bug reporting instructions, please see:
<http://gcc.gnu.org/bugs.html>

以下に示すように例を拡張します(または、以下に示すように例を拡張しました):

#include <stdio.h>
#include <complex.h>

int main(void)
{
    double complex test1, test2, test3, test4, test5, test6, test7, test8;

    test1 = 81141117.0;
    test2 = 81141117.0 + I * 0;
    test3 = 81141117 + I * 0.0;
    test4 = 81141117 + I * 0;
    test5 = (float)81141117 + I * 0;
    test6 = 81141117 + I * (float)0;
    test7 = 81141117.F + I * 0;
    test8 = 81141117 + I * 0.F;
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test1), (long)cimag(test1), (long)creal(test2), (long)cimag(test2));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test3), (long)cimag(test3), (long)creal(test4), (long)cimag(test4));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test5), (long)cimag(test5), (long)creal(test6), (long)cimag(test6));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test7), (long)cimag(test7), (long)creal(test8), (long)cimag(test8));
}

私が得た出力は次のとおりです。

81141117 + 0 I, 81141117 + 0 I
81141117 + 0 I, 81141120 + 0 I
81141120 + 0 I, 81141120 + 0 I
81141120 + 0 I, 81141120 + 0 I

ご覧のとおり、明示的な(float)キャストまたは明示的な float 定数があった最後の 2 行は、問題のある行と同じ結果を生成します (ただし、値は正当です)。

CMPLX, CMPLXF(そしておそらくCMPLXL) マクロを試してみたい (あるいはしたくない) かもしれません。「興味深い」の定義に対して「興味深い」値を生成した場合にのみ、報告された例に追加します。


コンパイラのバージョン番号:

$ /usr/gcc/v4.7.1/bin/gcc --version
gcc (GCC) 4.7.1
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ /usr/bin/gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.65) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix
$
于 2012-11-28T07:03:05.290 に答える