Подтвердить что ты не робот

MinGW не создает предупреждений

Я успешно установил MinGW на 32-битной машине Windows 7 и попытался скомпилировать простую программу, используя либо командную строку, либо консоль MinGW.

Код имеет преднамеренную ошибку в инструкции printf:

#include <stdio.h>
#include <stdlib.h>
int main( void )
{
    printf("%d\n" , 3.14 ) ;
return 0 ;
}

Команда gcc -Wall hello.c дает правильное предупреждение: hello.c: 7: 2: warning: format '% d' ожидает аргумент типа 'int'...

Но команда gcc -std=c99 -Wall hello.c не дает никаких предупреждений.

Оба создают исполняемый файл a.exe(который запускает и дает тот же результат).

(Интересно, что команда gcc -std=gnu99 -Wall hello.c дает предупреждение.)

Я не знаю, было ли это ошибкой или что-то не так, но обе выглядят маловероятными, поскольку компилятор работает и успешно скомпилировал более крупный проект (но одно и то же предупреждение, конечно же, опущено при использовании -std = c99).

Мне не хватает информации.

(ps: Если у кого-то есть новая установка MinGW, пожалуйста, проверьте это.)

gcc версия 4.8.1 (GCC)

Обновление 1:

Определение _GNU_SOURCE перед включением stdio.h удаляет предупреждение даже с помощью gcc -Wall hello.c.

Обновление 2 (может быть менее актуально):

компилирование

 printf("%lf\n" , 3.14 ) ;

-std=c99 выходы флага: 0.000000

-std=gnu99 выходы: 3.140000

И компиляция:

 printf("%f\n" , 3.14 ) ;

-std=gnu99 и -std=c99 вывод: 3.140000

Обновление 3:

Функции, которые, как представляется, затронуты: printf, fprintf, snprintf, sprintf.

4b9b3361

Ответ 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.