I'm using C's complex arithmetic support and ran into some surprising and undesirable behavior. Complex values seem to be implicitly convertible to real ones, discarding the imaginary part.
Consider the following:
#include <complex.h>
#include <stdio.h>
float complex getComplex(float real, float imag)
{
return real + imag * I;
}
int main()
{
const float /* missing complex! */ c = getComplex(25, 6) / getComplex(2, 4);
printf("%f + %f J\n", crealf(c), cimag(c));
return 0;
}
I would expect to receive some warning that I am assigning a float complex
to a float
or perhaps calling crealf
and cimagf
on a non-complex value, but this builds cleanly on GCC 5.1, even with -Wall -Wextra -Wconversion
switches. Clang 3.6.1 at least emits such a warning:
wut.c:11:62: warning: implicit conversion discards imaginary component: '_Complex float' to 'float'
[-Wconversion]
const float /* missing complex! */ c = getComplex(25, 6) / getComplex(2, 4);
~ ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
Why can complex values "collapse" to real ones? Is there some verbiage about this in the standard? And is there some additional switch for GCC that can provide warnings about this behavior? It has already bitten us, and switching toolchains (to clang) for this project isn't feasible at present time.
C11 final draft (N1570), 6.3.1.7 paragraph 2:
Real types are integer and real floating types.
The C99 rationale explains the motivation behind this:
And (numbering is identical to C11):