stringtranslate.com

С99

Обложка документа стандартов C99

C99 (ранее C9X , официально ISO/IEC 9899:1999 ) — предыдущая версия открытого стандарта языка программирования C. [1] Она расширяет предыдущую версию ( C90 ) новыми функциями для языка и стандартной библиотеки , а также помогает реализациям лучше использовать имеющееся компьютерное оборудование, такое как арифметика с плавающей точкой IEEE 754-1985 и технология компилятора. [2] Версия C11 стандарта языка программирования C, опубликованная в 2011 году, обновляет C99.

История

После того, как ANSI выпустил официальный стандарт для языка программирования C в 1989 году, который стал международным стандартом в 1990 году, спецификация языка C некоторое время оставалась относительно статичной, в то время как C++ продолжал развиваться, в основном в ходе собственных усилий по стандартизации. Нормативная поправка 1 создала новый стандарт для C в 1995 году, но только для исправления некоторых деталей стандарта 1989 года и добавления более обширной поддержки международных наборов символов. Стандарт подвергся дальнейшему пересмотру в конце 1990-х годов, что привело к публикации ISO/IEC 9899:1999 в 1999 году, который был принят в качестве стандарта ANSI в мае 2000 года. Язык, определенный этой версией стандарта, обычно называют «C99». Международный стандарт C поддерживается рабочей группой ISO/IEC JTC1/SC22 /WG14.

Дизайн

C99 по большей части обратно совместим с C89, но в некоторых отношениях он строже. [3]

В частности, объявление, в котором отсутствует спецификатор типа, больше не intподразумевается. Комитет по стандартам C решил, что для компиляторов важнее диагностировать непреднамеренное упущение спецификатора типа, чем молча обрабатывать устаревший код, который полагался на implicit int. На практике компиляторы, скорее всего, выведут предупреждение, затем предполагают intи продолжат трансляцию программы.

C99 представил несколько новых функций, многие из которых уже были реализованы как расширения в нескольких компиляторах: [4]

Части стандарта C99 включены в текущую версию стандарта C++ , включая целочисленные типы, заголовки и библиотечные функции. Массивы переменной длины не входят в число этих включенных частей, поскольку библиотека стандартных шаблонов C++ уже включает в себя подобную функциональность.

Поддержка операций с плавающей точкой IEEE 754

Главной особенностью C99 является его поддержка чисел, и в частности его поддержка доступа к функциям IEEE 754-1985 (также известного как IEC 60559) оборудования с плавающей точкой , присутствующего в подавляющем большинстве современных процессоров (определено в «Приложении F IEC 60559 Арифметика с плавающей точкой»). Платформы без оборудования IEEE 754 также могут реализовать его программно. [2]

На платформах с плавающей точкой IEEE 754:

FLT_EVAL_METHOD == 2имеет тенденцию ограничивать риск ошибок округления, влияющих на численно нестабильные выражения (см. обоснование дизайна IEEE 754 ) и является разработанным методом по умолчанию для оборудования x87 , но приводит к неинтуитивному поведению для неосторожного пользователя; [9] FLT_EVAL_METHOD == 1 был методом оценки по умолчанию, первоначально использовавшимся в K&R C , который продвигал все числа с плавающей точкой к double в выражениях; а FLT_EVAL_METHOD == 0также широко используется и определяет строгое «вычислять по типу» операндов. (Для gcc являетсяFLT_EVAL_METHOD == 2 методом по умолчанию для 32-битной x86 и FLT_EVAL_METHOD == 0является методом по умолчанию для 64-битной x86-64, но FLT_EVAL_METHOD == 2может быть указан для x86-64 с помощью параметра -mfpmath=387.) До C99 компиляторы могли округлять промежуточные результаты непоследовательно, особенно при использовании оборудования с плавающей точкой x87 , что приводило к поведению, специфичному для компилятора; [10] такие непоследовательности не допускаются в компиляторах, соответствующих C99 (приложение F).

Пример

Следующий аннотированный пример кода C99 для вычисления функции цепной дроби демонстрирует основные функции:

#include <stdio.h> #include <math.h> #include <float.h> #include <fenv.h> #include <tgmath.h> #include <stdbool.h> #include <assert.h> двойной compute_fn ( двойной z ) // [1]   { #pragma STDC FENV_ACCESS ВКЛ // [2] утверждать ( FLT_EVAL_METHOD == 2 ); // [3]    если ( иснан ( z )) // [4]   puts ( "z не является числом" ); если ( isinf ( z ))  puts ( "z бесконечно" ); длинный двойной r = 7,0 - 3,0 / ( z - 2,0 - 1,0 / ( z - 7,0 + 10,0 / ( z - 2,0 - 2,0 / ( z - 3,0 )))); // [5, 6]                      feclearexcept ( FE_DIVBYZERO ); // [7]  bool поднят = fetestexcept ( FE_OVERFLOW ); // [8]     если ( поднятый )  puts ( "Непредвиденное переполнение." ); вернуть г ; }int main ( пустота ) { #ifndef __STDC_IEC_559__ puts ( "Предупреждение: __STDC_IEC_559__ не определено. Плавающая точка IEEE 754 поддерживается не полностью." ); // [9]  #endif #pragma STDC FENV_ACCESS ВКЛ #ifdef ТЕСТ_ЧИСЛОВАЯ_СТАБИЛЬНОСТЬ_ВВЕРХ fesetround ( FE_UPWARD ); // [10]  #elif ТЕСТ_ЧИСЛОВАЯ_СТАБИЛЬНОСТЬ_ВНИЗ fesetround ( FE_DOWNWARD ); #endif printf ( "%.7g \n " , compute_fn ( 3.0 ));  printf ( "%.7g \n " , Compute_fn ( NAN ));  вернуть 0 ; }

Сноски:

  1. Компилировать с помощью:gcc -std=c99 -mfpmath=387 -o test_c99_fp test_c99_fp.c -lm
  2. Поскольку в этой функции обрабатываются флаги состояния IEEE 754, эта #pragma необходима для того, чтобы компилятор не мог неправильно переставить такие тесты при оптимизации. (Прагмы обычно определяются реализацией, но те, которые имеют префикс , STDCопределены в стандарте C.)
  3. C99 определяет ограниченное количество методов оценки выражений: текущий режим компиляции можно проверить, чтобы убедиться, что он соответствует предположениям, на основе которых был написан код.
  4. Можно проверить и установить специальные значения, такие как NaN и положительная или отрицательная бесконечность.
  5. long doubleопределяется как IEEE 754 double extended или quad precision, если доступно. Использование более высокой точности, чем требуется для промежуточных вычислений, может минимизировать ошибку округления [11] ( typedef double_t может использоваться для кода, который является переносимым при всех FLT_EVAL_METHODs).
  6. Основная функция для оценки. Хотя кажется, что некоторые аргументы этой непрерывной дроби, например, 3.0, приведут к ошибке деления на ноль, на самом деле функция хорошо определена при 3.0, а деление на 0 просто вернет +бесконечность, которая затем правильно приведет к конечному результату: IEEE 754 определен так, чтобы не перехватывать такие исключения по умолчанию, и разработан так, чтобы их очень часто можно было игнорировать, как в этом случае. (Если FLT_EVAL_METHODопределено как 2, то все внутренние вычисления, включая константы, будут выполняться с точностью long double; если FLT_EVAL_METHODопределено как 0, то для обеспечения этого необходимо дополнительное внимание, включая возможные дополнительные приведения и явное указание констант как long double.)
  7. Поскольку поднятый флаг деления на ноль в данном случае не является ошибкой, его можно просто снять, чтобы очистить флаг для использования в последующем коде.
  8. В некоторых случаях другие исключения могут рассматриваться как ошибка, например, переполнение (хотя на самом деле можно показать, что в данном случае этого произойти не может).
  9. __STDC_IEC_559__должен быть определен только в том случае, если «Приложение F IEC 60559 Арифметика с плавающей точкой» полностью реализовано компилятором и библиотекой C (пользователи должны знать, что этот макрос иногда определяется, хотя это не должно быть так).
  10. Режим округления по умолчанию — округление до ближайшего (с четным правилом округления в половинных случаях) для IEEE 754, но явная установка режима округления в сторону + и - бесконечности (путем определения TEST_NUMERIC_STABILITY_UPи т. д. в этом примере при отладке) может использоваться для диагностики числовой нестабильности. [12] Этот метод можно использовать, даже если compute_fn()он является частью отдельно скомпилированной двоичной библиотеки. Но в зависимости от функции числовая нестабильность не всегда может быть обнаружена.

Определение версии

Стандартный макрос __STDC_VERSION__определен со значением, 199901Lуказывающим на доступность поддержки C99. Как и __STDC__макрос для C90, __STDC_VERSION__может использоваться для написания кода, который будет компилироваться по-разному для компиляторов C90 и C99, как в этом примере, который гарантирует, что inlineон доступен в любом случае (путем замены его на staticв C90, чтобы избежать ошибок компоновщика).

#if __STDC_VERSION__ >= 199901L /* "inline" — это ключевое слово */ #else # определить inline static #endif 

Реализации

Большинство компиляторов C поддерживают по крайней мере некоторые функции, представленные в C99.

Исторически сложилось так, что Microsoft не спешила внедрять новые функции C в свои инструменты Visual C++ , вместо этого сосредоточившись в основном на поддержке разработок в стандартах C++. [13] Однако с выпуском Visual C++ 2013 Microsoft реализовала ограниченное подмножество C99, которое было расширено в Visual C++ 2015. [14]

Будущая работа

После ратификации стандарта C 1999 года рабочая группа по стандартам подготовила технические отчеты, определяющие улучшенную поддержку встроенной обработки, дополнительные типы символьных данных ( поддержка Unicode ) и библиотечные функции с улучшенной проверкой границ . Продолжается работа над техническими отчетами, касающимися десятичных чисел с плавающей точкой , дополнительных математических специальных функций и дополнительных функций динамического распределения памяти . Комитеты по стандартам C и C++ сотрудничают в разработке спецификаций для потокового программирования.

Следующая редакция стандарта C, C11 , была ратифицирована в 2011 году. [41] Комитет по стандартам C принял руководящие принципы, которые ограничили принятие новых функций, которые не были протестированы существующими реализациями. Много усилий было потрачено на разработку модели памяти , чтобы прояснить точки последовательности и поддержать потоковое программирование.

Смотрите также

Ссылки

  1. ^ "ISO/IEC 9899:1999 - Языки программирования - C". Iso.org. 8 декабря 2011 г. Получено 8 апреля 2014 г.
  2. ^ ab "IEEE 754 Support in C99" (PDF) . IEEE . Архивировано из оригинала (PDF) 28 октября 2017 г. . Получено 15 июля 2021 г. .
  3. ^ "Стандарты - Использование коллекции компиляторов GNU (GCC)". Gcc.gnu.org . Получено 8 апреля 2014 г. .
  4. ^ "Параметры диалекта C - Использование коллекции компиляторов GNU (GCC)". Gcc.gnu.org. 6 мая 2009 г. Получено 8 апреля 2014 г.
  5. ^ «Использование коллекции компиляторов GNU (GCC): назначенные инициализаторы». gnu.org . Получено 18 сентября 2019 г. .
  6. ^ «Использование коллекции компиляторов GNU (GCC): составные литералы». gnu.org . Получено 31 января 2016 г. .
  7. Ульрих Дреппер (23 октября 2007 г.). «Что каждый программист должен знать о памяти». LWN.net . Получено 3 апреля 2015 г.
  8. ^ Спецификация ISO/IEC 9899:1999, TC3 (PDF) . стр. 119, § 6.7.5.3 Деклараторы функций (включая прототипы), параграф 7.
  9. ^ Дуг Прист (1997). «Различия между реализациями IEEE 754».
  10. Джек Воэр (1 ноября 1997 г.). «Беседа с Уильямом Кэханом».
  11. Уильям Кахан (11 июня 1996 г.). «Пагубное влияние компьютерных тестов на прикладную математику, физику и химию» (PDF) .
  12. ^ Уильям Кахан (11 января 2006 г.). «Насколько бесполезны бездумные оценки округления в вычислениях с плавающей точкой?» (PDF) .
  13. Питер Брайт (29 июня 2013 г.). «C99 наконец-то признан, поскольку Microsoft прокладывает свой путь к C++14». Ars Technica . Получено 9 января 2015 г.
  14. ^ abc Бреннер, Пат. "Что нового для Visual C++ в Visual Studio 2015". Microsoft Developer Network . Получено 27 апреля 2015 г.
  15. ^ "Использование x86 Open64 Compiler Suite" (PDF) . Developer.amd.com. Архивировано (PDF) из оригинала 24 января 2022 г. . Получено 2 марта 2022 г. .
  16. ^ "cc65 - бесплатный компилятор C для систем на базе 6502" . Получено 14 сентября 2011 г.
  17. ^ "C/C++ interpretationr Ch C99 features". SoftIntegration, Inc. 15 февраля 2008 г. Получено 15 февраля 2008 г.
  18. ^ "Clang Compiler User's Manual" . Получено 14 октября 2017 г. .
  19. ^ "Документация и руководство пользователя проверенного компилятора CompCert C (версия 3.10)". 19 ноября 2021 г. Получено 3 марта 2022 г.
  20. ^ "libfirm homepage" . Получено 4 февраля 2014 г. .
  21. ^ "Реализация языка C - Digital Mars" . Получено 14 сентября 2011 г.
  22. ^ "Статус функций C99 в GCC". Free Software Foundation, Inc. 28 июля 2021 г. Получено 13 августа 2021 г.
  23. ^ "Статус функций C99 в GCC 4.6". Free Software Foundation, Inc. 23 мая 2013 г. Получено 23 мая 2013 г.
  24. ^ "Статус функций C99 в GCC 4.7". Free Software Foundation, Inc. 23 мая 2013 г. Получено 23 мая 2013 г.
  25. ^ "Семантика чисел с плавающей точкой в ​​GCC". 20 июля 2018 г. Получено 12 августа 2018 г.
  26. ^ "IBM C для AIX, V6.0 теперь поддерживает стандарт C99". 2 июля 2002 г. Получено 31 января 2016 г.
  27. ^ "IBM - XL C/C++ для AIX" . Получено 31 января 2016 г. .
  28. ^ "Поддержка IBM Rational Logiscope для стандарта C99 — США". 24 февраля 2012 г. Получено 31 января 2016 г.
  29. ^ «Вопросы и ответы читателей: Что насчет VC++ и C99?». Sutter's Mill . 3 мая 2012 г. Получено 31 января 2016 г.
  30. ^ "A.27 Использование массивов переменной длины C99". Microsoft . Получено 31 января 2016 г. .
  31. ^ "Microsoft to C99 Developers: Use ISO C++". InfoQ . Получено 31 января 2016 г. .
  32. ^ "Поддержка библиотеки C99 в Visual Studio 2013". Microsoft. 19 июля 2013 г. Получено 31 января 2016 г.
  33. ^ "C++11/14 STL Features, Fixes, And Breaking Changes In VS 2013". Blogs.msdn.com. 28 июня 2013 г. Получено 8 апреля 2014 г.
  34. ^ «Объявление о полной поддержке препроцессора, соответствующего C/C++, в MSVC». Microsoft. 27 марта 2020 г. Получено 17 сентября 2020 г.
  35. ^ "C99 conformance in Open Watcom". Архивировано из оригинала 3 мая 2015 года . Получено 25 сентября 2015 года .
  36. ^ "Обзор Pelles C". Январь 2013. Архивировано из оригинала 13 марта 2022 года . Получено 2 марта 2022 года .
  37. ^ "Sun Studio 12: C Compiler 5.9 Readme". Sun Microsystems, Inc. 31 мая 2007 г. Получено 23 сентября 2012 г.
  38. ^ "Справочная документация по компилятору Tiny C" . Получено 31 января 2016 г.
  39. ^ Согласно списку TODO проекта, сложные типы — единственная отсутствующая функция C99. Массивы переменной длины были добавлены в TCC 0.9.26 [1]
  40. ^ "TCC : Tiny C Compiler" . Получено 31 января 2016 г. .
  41. ^ "Стандарты - Использование коллекции компиляторов GNU (GCC)". Gcc.gnu.org . Получено 8 апреля 2014 г. .

Дальнейшее чтение

Внешние ссылки