fr33f0r4ll

自分用雑記

windows, gcc, long double, prinf

Cでlong doubleをフォーマット出力しようとしたら失敗したので備忘録。
調べてみると解決策っぽいのが見つかったが日本語情報はなかったのでメモしておく。 stackoverflowにあった。

問題

環境はWindows10、MinGW64のターミナルからgccで、long doubleが16バイトの環境になってる。
コードはこんな感じ。

#include <stdio.h>

int main() {
    long double ld = 0.1L;

    printf("sizeof(long double): %d\n", sizeof(long double));  
    printf("sizeof(double): %d\n", sizeof(double));

    printf("ld = %Le\n", ld);

    return 0;
}

コンパイルして実行

$ gcc test.c
$ ./a.exe
sizeof(long double): 16
sizeof(double): 8
ld = 3.205300e-317

MinGWだと内部でWindowsのruntimeで出力しようとしているのが原因っぽい。 Windowsだとsizeof(long double) == 8だけど、MinGWgccだとsizeof(long double) == 16だから不整合が起きる。

解決策

解決策は-D__USE_MINGW_ANSI_STDIOのオプションをコンパイル時に指定すればいい。 こんな感じになる。

$ gcc test.c -D__USE_MINGW_ANSI_STDIO
$ ./a.exe
sizeof(long double): 16
sizeof(double): 8
ld = 1.000000e-001

こうすればANSI規格かなんかになっているstdioを優先して使ってくれるような感じで上手くいくっぽい。 詳しく調べてないから具体的には分からない。

long double自体ビット長が環境によって結構違うっぽい(80bitとかもあるみたい)なので、使うのはできるだけ避けるかsizeofでビット長が想定している長さかをチェックした方がいい。
gccなら拡張機能として128bitの浮動小数点があるのでそっちが使えるかもしれない。