C99 complex double int or float imaginary zero affecting the real value

Can someone explain why the following code produces different output for the variable test4 compared to the other 3? I checked this with gcc version 4.2.1 and 4.5.3 (and others in between). A.

Maybe I'm missing something obvious, but it looks pretty simple ...

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

Output:

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

It seems like test4, which has only integer members, advances to float instead of the declared double, and rounding goes into the game.

+4
source share
1 answer

I tested GCC 4.7.1 on Mac OS X 10.7.5 (built-in GCC), as well as the /usr/bin/gcc and /usr/bin/clang , and they all give the same result you are reporting.

I agree with your analysis that instead of double should be a conversion to float when both members of a complex number are expressed as integers. Standard C 2011 includes an example:

ISO / IEC 9899: 2011 §6.7.9 Initialization

¶24 EXAMPLE 1 Provided that <complex.h> was #include d, declarations

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

define and initialize i with a value of 3 and c with a value of 5. 0 + i3. 0.

This clearly indicates that you should be able to write integer expressions and get a valid double complex (although the examples are non-normative). However, it does not take into account whether the integer value should be converted to float before converting to double , but there is nowhere else in the language that would do it automatically (obviously, you can force it), so this is unlikely as the intended interpretation.

In general, I think that this is most likely to be a mistake that could be reported to the GCC team (and this is not what I advocate by doing it frivolously). If you run gcc --help , the output ends with a message:

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

I would expand your example as shown below (or rather, I expand your example as shown below):

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

The output I received was:

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

As you can see, the last two lines, in which there were explicit floating-point constants or explicit ones, give the same results as your problem string (but the values ​​are legal).

You could (or don't want to) experiment with the CMPLX , CMPLXF (and possibly CMPLXL ) CMPLXL ; I would add them only to the given example if they produced “interesting” values ​​for some definition of “interesting”.


Compiler version numbers:

 $ /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 $ 
+4
source

All Articles