Ответ 1
Проблема с отсутствием предупреждения при использовании параметра std=c99
выглядит так, потому что MinGW 4.8.1 preprocesses stdio.h
немного отличается для семейства функций printf()
при использовании -std=c99
по сравнению с тем, когда -std=gnu99
.
Примечание. Я смотрю на MinGW 4.8.1 от TDM. Я думаю, что другие дистрибутивы могут отличаться в этих деталях.
У MinGW были проблемы с совместимостью с форматированием значений с плавающей запятой из-за его исторической зависимости от msvcrt.dll
для среды выполнения C и того факта, что MSVC использует 64-битное представление для long double
, в то время как gcc использует 96-битный ( или 128-бит на x64). См. gcc: printf и long double приводит к неправильному выходу. [C - Преобразование типа messes up] для некоторых деталей. Более поздние версии MinGW предоставили собственную реализацию семейства функций printf()
(с префиксом __mingw_
для имени) в libmingwex.a
для решения этих проблем.
Заголовочные файлы _mingw.h
и stdio.h
определяют, будут ли реализованы реализации libmingwex.a
или реализации msvcrt.dll
.
Похоже, что если запрашивается соответствие ANSI, MinGW будет использовать реализации libmingwex.a
(есть еще несколько способов получить эту конфигурацию - посмотрите подробности в заголовках). Проводка вызова пользователя printf()
в реализацию __mingw_printf()
в libmingwex.a
выполняется с помощью stdio.h
, определяющего статическую встроенную реализацию printf()
, которая представляет собой тонкую оболочку вокруг вызова __mingw_vfprintf()
. По-видимому, -Wformat
не применяется к версиям семейных функций printf()
, которые компилятор не считает частью библиотеки (разумное предположение - компилятор ничего не знает об этих функциях). Эту проблему можно устранить, применив соответствующий атрибут функции (например: __attribute__ ((format (printf, 1, 2)))
) к статическим встроенным функциям оболочки.
Другая проблема, которую вы обнаружили, где printf("%lf\n", 3.14)
печатает 0.000000
при использовании std=c99
, выглядит ошибкой в реализации libmingwex.a
__mingw_vfprintf()
. Похоже, что __mingw_vfprintf()
ошибочно интерпретирует "%lf"
как аргумент long double
. Я не удивлен этим - мне всегда нужно искать, есть ли %lf
double
или long double
.