标识符“creal”未定义 – 在Mac上可见,但在Linux上不可见

下面的代码是错误的还是在Mac上的标题有问题? 这个错误并没有出现在Linux上,这导致我得出这样的结论:这不是错误的代码,虽然在Linux上编译成功并不是一个严格的ISO合规性testing。

源代码(MCVE)

#include <stdio.h> #include <complex.h> void foo(const double *A, int *size){ for(int i=0;i < size[0]; ++i){ for(int j=0;j < size[1]; ++j){ printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]])); } } } 

苹果电脑

系统信息

 $ uname -a Darwin redacted 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64 

Intel编译器

 $ icpc -v icpc version 16.0.2 (gcc version 4.9.0 compatibility) $ icpc -c ttc-creal.cpp ttc-creal.cpp(7): error: identifier "creal" is undefined printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]])); ^ ttc-creal.cpp(7): error: identifier "cimag" is undefined printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]])); ^ compilation aborted for ttc-creal.cpp (code 2) 

LLVM编译器

 $ clang++ -v Apple LLVM version 7.3.0 (clang-703.0.29) Target: x86_64-apple-darwin15.4.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin $ clang++ -c ttc-creal.cpp ttc-creal.cpp:7:33: error: use of undeclared identifier 'creal' printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]])); ^ ttc-creal.cpp:7:60: error: use of undeclared identifier 'cimag' printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]])); ^ 2 errors generated. 

Linux的

系统信息

 $ uname -a Linux redacted 2.6.32-573.18.1.el6.centos.plus.x86_64 #1 SMP Wed Feb 10 18:09:24 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux 

GNU编译器

 $ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/opt/gcc/5.3.0/libexec/gcc/x86_64-unknown-linux-gnu/5.3.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /home/redacted/Work/GCC/gcc-5.3.0/configure --prefix=/opt/gcc/5.3.0 --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --enable-languages=c,c++,fortran --with-tune=native --enable-bootstrap --enable-lto --with-mpfr --with-isl --with-gmp --with-mpc --with-cloog --enable-gold --enable-ld --disable-multilib Thread model: posix gcc version 5.3.0 (GCC) $ g++ -c ttc-creal.cpp <no error> 

Intel编译器

 $ icpc -v icpc version 17.0.0 Beta (gcc version 5.3.0 compatibility) $ icpc -c ttc-creal.cpp <no error> 

LLVM编译器

 $ clang++ -v clang version 3.4.2 (tags/RELEASE_34/dot2-final) Target: x86_64-redhat-linux-gnu Thread model: posix Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.4 Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.7 Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.4.4 Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.4.7 Selected GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.7 $ clang++ -c ttc-creal.cpp <no error> 

调查

我已经通读了我Mac上所有相关的complex.hccomplexcomplex标题,但是看不到这个问题的明显原因。

这只是铿锵的C ++标准的阅读 – 看到这个答案 – 这对我来说似乎是正确的。 基本上,你不应该在C ++中使用C99复杂类型和相关函数,而应该使用std::complex<T> 。 这两种复杂类型应该是布局兼容的,你应该能够在C和C ++代码之间传递复杂的数据。

g++complex.h包含了<ccomplex> (在C ++ 11模式下)和C <complex.h> ,因此代码使用GCC编译(从我自己的Homebrew开始)。 我没有英特尔编译器的OS X,但你可以检查它与icpc -E ttc-creal.cpp | grep complex icpc -E ttc-creal.cpp | grep complex并观察包含文件扩展的顺序。

铛:

 $ clang++ -E ttc-creal.cpp | grep "^# 1 " | grep complex # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex.h" 1 3 # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ccomplex" 1 3 # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex" 1 3 

GCC:

 $ g++-5 -E ttc-creal.cpp | grep "^# 1 " | grep complex # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex.h" 1 3 # 1 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h" 1 3 4 $ g++-5 -std=c++11 -E ttc-creal.cpp | grep "^# 1 " | grep complex # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex.h" 1 3 # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/ccomplex" 1 3 # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex" 1 3 # 1 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h" 1 3 4 

你可以强制Clang包含<path to SDK>/usr/include/complex.h ,例如:

 #include "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h" 

你的MCVE会编译,但这样做可能是一个很坏的想法(tm)。

顺便说一下,在FreeBSD 10.2-RELEASE中使用Clang 3.4.1(错误)和GCC 4.8.5(成功)也观察到相同的行为。

所有的荣誉都归功于Potatoswatter – 顶部引用的答案的作者。