Делает ли __встроенный_isnan GCC что-то другое, чем isnan?

#gcc #floating-point #c99 #built-in #isnan

Вопрос:

В описании встроенных модулей GCC говорится::

GCC предоставляет встроенные версии макросов сравнения ISO C99 с плавающей запятой, которые позволяют избежать возникновения исключений для неупорядоченных операндов. Они имеют те же имена, что и стандартные макросы ( isgreater, isgreaterequal, isless, islessequal, islessgreater и isunordered) , с префиксом _buildin. Мы хотим, чтобы разработчик библиотеки мог просто #определить каждый стандартный макрос в соответствии с его встроенным эквивалентом. Таким же образом GCC предоставляет встроенные модули fpclassify, isfinite, isinf_sign, isnormal и signbit, используемые с префиксом _buildin. Встроенные функции isinf и isnan отображаются как с префиксом _buildin, так и без него.


Итак, я не совсем в состоянии разобрать это. Когда сравнения с плавающей запятой должны вызывать исключения? Выполняет ли стандарт C мандат, который они выполняют? А они этого не делают? Ничего не предписывает? И — __builtin_isnan() действует ли иначе, чем isnan() ?

Ответ №1:

По исключению здесь документы GCC ссылаются на исключения IEEE 754 с плавающей запятой. Если вы сделаете что-то вроде

 a < b
 

и одним из операндов является NaN, будет вызвано исключение FP (недопустимое). Это означает, что бит в FPU будет оставаться установленным до тех пор, пока он явно не будет очищен программистом. Используя вместо isgreater этого / isless /и т. Д., программист может избежать запуска исключения FP.

Комментарии:

1. Итак, текст «исключение» относится только к LT/GT/LTE/GTE, а не к чему-либо еще? т. е. не isnan ?

2. Да, моя интерпретация текста, который вы процитировали, заключается в том, что GCC предоставляет другие встроенные модули, чтобы стандартные реализации библиотек могли их использовать, и часть исключения применяется только к сравнениям.

3. Интерпретация-это хорошо, но… Я хочу знать это наверняка.

4. Если вам нужно что-то более авторитетное, чем документы, я предлагаю вам написать несколько небольших тестовых программ и посмотреть, как они себя ведут и какой ASM они генерируют, или посмотреть исходные тексты компилятора (я бы предположил, что первым местом для поиска будет поиск встроенного IN_ISNAN в gcc/встроенных.c).

5. Хорошая идея. Я совершил ошибку, пытаясь найти isnan() в источниках glibc, и подагра обескуражила 🙁