Статус __STDC_IEC_559__ с современными компиляторами C

В C99 добавлен макрос __STDC_IEC_559__, который может использоваться для проверки соответствия стандартного и стандартного библиотек стандарту ISO/IEC/IEEE 60559 (или IEEE 754).

В соответствии с ответами на этот вопрос
how-to-check-that-ieee-754-single-precision-32-bit-floating-point-presentation большинство компиляторов C не устанавливают макрос препроцессора __STDC_IEC_559__.

В соответствии с документацией GCC он не определяет __STDC_IEC_559__.

Я тестировал это с помощью GCC 4.9.2 и Clang 3.6.0, используя как glibc 2.21, используя следующий код.

//test.c 
//#include <features.h>    
int main(void) {
#if defined ( __STDC_IEC_559__ )
//#if defined ( __GCC_IEC_559__ )
    return 1;
#else
    return 0;
#endif
}

а затем

echo $?

Это показывает, что с этим кодом __STDC_IEC_559__ определяется с помощью GCC, но не с Clang. Затем я сделал gcc -E, и он показал, что файл stdc-predef.h включен. Этот файл определяет __STDC_IEC_559__.

/* glibc intent is to support the IEC 559 math functionality, real
   and complex.  If the GCC (4.9 and later) predefined macros
   specifying compiler intent are available, use them to determine
   whether the overall intent is to support these features; otherwise,
   presume an older compiler has intent to support these features and
   define these macros by default.  */

#ifdef __GCC_IEC_559
# if __GCC_IEC_559 > 0
#  define __STDC_IEC_559__              1
# endif
#else
# define __STDC_IEC_559__               1
#endif

Это подтверждает, что он glibc определяет этот макрос, а не GCC.

Однако, когда я включаю features.h (или stdio.h), этот файл также входит в состав Clang и что __STDC_IEC_559__ определяется.

So __STDC_IEC_559__ определяется как GCC, так и Clang (с заголовком glibc), который, похоже, не согласен с ответом на первый вопрос, с которым я связан.

Затем я протестировал musl (например, musl-gcc -test.c), который является другой стандартной библиотекой, чем glibc. Это показало, что __STDC_IEC_559__ не определяется с помощью musl.

Как я понимаю, стандартная библиотека C не определяет основную алгебру с плавающей запятой. Например, стандартная библиотека C не определяет результат 1.0/-0.0. Это определяется компилятором.

Мои вопросы (оцениваются в порядке важности для меня):

  • Почему __STDC_IEC_559__ определяется glibc, а не компилятором?
  • Если бы я создал свою собственную стандартную библиотеку, и я хотел бы определить __STDC_IEC_559__, мне нужно было бы знать, что компилятор уже соответствует IEEE 754 для операций, не определенных в моей стандартной библиотеке (например, 1.0/-0.0). Есть ли документы для этого или макроса для проверки на это?
  • Википедия заявляет, что "пользователи должны знать, что этот макрос (__STDC_IEC_559__) иногда определяется, пока он не должен быть". Является ли это утверждение еще точным?

Ответ 1

  • Я полагаю, что __STDC_IEC_559__ полагается на некоторые функции библиотеки и не может быть определен исключительно компилятором. Для получения дополнительной информации см. этот пост. Это не редкость для C - компилятор и библиотека C иногда должны взаимодействовать, чтобы реализовать весь стандарт.

  • То, о чем вы спрашиваете, зависит от компилятора. Я думаю, вам нужно будет получить специальное знание компилятора, чтобы это решить. В конкретном случае GCC он определяет макрос, чтобы рассказать вам. Найдите этот node руководства для __GCC_IEC_559.

  • Ну... я не знаю ответа на этот вопрос:-). Похоже, что исходное сообщение указывает, что да, GCC может определить __GCC_IEC_559, если он намерен реализовать IEEE 754, даже если он этого не делает.