最近のVisual C++ではC99もある程度サポートしているらしい。
- C99 library support in Visual Studio 2013 | Visual C++ Team Blog
- C++11/14/17 Features In VS 2015 RTM | Visual C++ Team Blog
- “Our C99 Standard Library implementation is complete, except for …” という記述がある。
上記ブログによると、 complex.h の関数もサポートしているらしい。しかし、コンパイラーは _Complex
型をサポートしていない。_Complex
型をサポートしていないのに、 complex.h の関数をサポートしているとはどういうことか。一体、 complex.h の関数は何を受け取って何を返すのか。
確認のため、次のような簡単な C++ のプログラムを書いてみた。
#include <stdio.h>
#include <complex.h>
#include <typeinfo>
int main(int argc, char *argv[]) {
puts(typeid(cabs).name());
}
結果は…。
double __cdecl(struct _C_double_complex)
どうやら、 _C_double_complex
という構造体が定義されて、それが double _Complex
型の代わりをしているようだ。多分この構造体の中身は、要素数2の double
の配列とかそんなんだろう。下記のコードは動いた。
#include <complex.h> #include <stdio.h> int main(int argc, char * argv[]) { _C_double_complex z = {1.0, 1.0}; // z = _Complex_I; /* error C2440: '=': cannot convert from '_Fcomplex' to '_C_double_complex' */ printf("%g\n", cabs(z)); }
_Complex_I
も定義されているようだが、型が違って、自動では変換されないっぽい。_C_double_complex
はコンパイラー的には特別扱いも何もない普通の構造体のようで、四則演算とか double
型との変換は何もできない。
ただ、_C_double_complex
型とC99の double _Complex
型にはバイナリレベルの互換性はあるはずなので、 msvcrt を使うC99対応コンパイラーで msvcrt に含まれる C99 complex の関数を利用できる可能性はある。
MinGW からの利用
msvcrt を使うC99対応コンパイラーと言えば、MinGWだ。まずは、MinGWのリンク先CRTを msvcrt.dll (VC6)ではなく msvcr120.dll (VC2013)に変える。(本当は最新の msvcr140.dll にリンクしたいところだが、手元のMinGWにはインポートライブラリが用意されていなかった)
この辺を変えるには、 specs ファイルというのをいじればいいらしい。$ gcc -dumpspecs
でデフォルトの specs ファイルを吐かせて、 -lmsvcrt
という箇所を -lmsvcr120
に変える。
ただ、これだけでは cabs
等のC99関数はMinGW側が用意したものが使われてしまうようだ。MinGW側が用意した cabs
関数は libmingwex.a
というファイルに含まれるようなので、これと msvcr120 をリンクする順番を入れ替える。
手順(MSYS2 の bash 上で実行):
$ gcc -dumpspecs | sed -e "s|-lmingwex %\{!mcrtdll=*:-lmsvcrt}|%\{!mcrtdll=*:-lmsvcr120} -lmingwex|" > msvcr120.specs
実際のプログラムで試してみる:
$ cat test.c
#include <complex.h>
#include <stdio.h>
int main(int argc, char * argv[]) {
double complex z = 1.0 + 1.0 * _Complex_I;
printf("%g\n", cabs(z));
}
$ gcc -std=gnu99 -specs=msvcr120.specs test.c
$ ./a.exe
1.41421
$ objdump -p a.exe | grep -i -A 40 msvcr120.dll
DLL Name: MSVCR120.dll
...
86b0 1082 _onexit
86ba 1147 _set_invalid_parameter_handler
86dc 1320 _unlock
86e6 1552 abort
86ee 1581 cabs ←msvcr120.dll の cabs 関数が使われている!
86f6 1590 calloc
8700 1674 exit
8708 1722 fprintf
...
参考にしたページ:MinGW GCCでlibcとしてmsvcrt.dll以外を使うまとめ – 自分についてのまとめサイト
結局
Visual C++ には _Complex
型のサポートはないし、MinGW には独自のC99サポートがあるし、やっぱり Visual C++ の complex.h の使いどころがわからん。別に、あったところで困るものではないが、なあ。