Hello everyone,
I'm developing a code that involves complex number (complex.h).In every line that has the imaginary I, such as:
float complex sum = 0.0 + 0.0*I;
or
noise[j][i] = conjf(eigen_vec[i][k] + eigen_vec[i+m-1][k]*I);
Keil gives that warning: " imaginary constants are a GNU extension".
In the complex.h has:
define I _Complex_I
Why is it giving that warning?Is my code going to work properly?How can I solve that warning?Thanks in advanced.
My other reply is pending investigation perhaps because of various links in it. The short reply is that using "i" (i.e. the small letter i) to create imaginary constants is not defined in the C standard (it is defined in C++14, but that std may not apply here as the question seems to be about C code), but such a facility is available for use if one is willing to utilize non-std extensions. If your code adheres to a std C11 or beyond, you can use CMPLX macros or __builtin_complex builtin function.
Hello,I tried __extension__ 1.0fi and it works without warning.However, when I set C11 in Keil, the complex.h is still the same and it does not recognize CMPLX. The complex.h does not have that macro as if it was from C99.
The armcc doc says:
In C99 mode, the compiler supports complex and imaginary numbers. In GNU mode, the compiler supports complex numbers only.
The warning implies that you are running the compiler in GNU mode. If armcc says they support imaginary numbers in C99 mode, that could mean that they have support for _Imaginary_I; i.e. the macro I resolves to _Imaginary_I. You could try compiling with -std=c99. With this way, you can use the I macro without running into the warning, and no other workaround (like __extension__ or CMPLX) should be required.
In your complex.h do you see _Imaginary_I macro defined?
Edit: en.cppreference.com says that the macro CMPLX is based on _Imaginary_I, so you could even write it on your own, like so:
#define CMPLX(x, y) ((double complex)((double)(x) + _Imaginary_I * (double)(y)))
Similarly for CMPLXF and CMPLXL.
Hello,
For unknown reason, the _Imaginary_I and I is not working regardless if I use c99, c11, gnu99, or gnu11. When I define the compiler, it changes the flags in Keil.
That is the compiler flags: "-xc -std=c11 --target=arm-arm-none-eabi -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar"
When I change to c99, c11, gnu99, or gnu11, the "-std=" flag also changes.
/* imaginary types not supported in gnu mode */# if !defined(__GNUC__) && !defined(__ARM_NO_IMAGINARY_TYPE)# define imaginary _Imaginary# define _Imaginary_I ((float _Imaginary)__I__)# define I _Imaginary_I# else# define I _Complex_I# endif
Okay. So the header is ready to accept _Imaginary_I but only in non-GNU mode and only if __ARM_NO_IMAGINARY_TYPE is not defined.
If you copy the compiler command line including flags but without the input and output files, you can see the compilers preprocessor defines. For e.g., "gcc -xc -std=c11 --target=arm-arm-none-eabi -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar -dM -E - < /dev/null". I think that __ARM_NO_IMAGINARY_TYPE should turn out to be defined, and so there might actually be no _Imaginary_I support, even though the header has been ready to accept such types.
In that case, __extension__ is the workaround.
Thank you very much for your response and the others too.However, just out of curiosity, is there a way to modify __ARM_NO_IMAGINARY_TYPE? Where is that macro?
I think that it is a compiler-defined macro, so it must be in the compiler's source-code. The compiler must be setting its value depending on the flags passed and the actual features it can support.
Edit: One can undefine that macro by #undef, but that does not mean that the imaginary support also becomes available. If that macro is defined, it is an indication that the selected flags either prevent the compiler from providing the imaginary type, or that the compiler has no support for that type at all.