C99

редактировать
Стандарт языка программирования C, редакция 1999 г. Обложка документа стандартов C99

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

Содержание
  • 1 История
  • 2 Дизайн
  • 3 Поддержка операций с плавающей запятой IEEE 754
    • 3.1 Пример
  • 4 Определение версии
  • 5 Реализации
  • 6 Дальнейшая работа
  • 7 См. Также
  • 8 Ссылки
  • 9 Дополнительная литература
  • 10 Внешние ссылки
История

После 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, но в некоторых отношениях он строже.

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

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

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

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

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

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

  • floatопределяется как IEEE 754 single precision, doubleопределяется как double precision, а long double определяется как IEEE 754 расширенная точность (например, Intel 80- бит двойная расширенная точность на платформах x86 или x86-64 ), или некоторая форма четырехкратной точности, если возможно; в противном случае это двойная точность.
  • Четыре арифметических операции и квадратный корень правильно округлены, как определено в IEEE 754.
    FLT_EVAL_METHODfloatdoubleдвойной двойной
    0поплавокдвойнойдлинный двойной
    1двойнойдвойнойдлинный двойной
    2длинный двойнойlong doublelong double
  • Оценка выражения определяется для выполнения одним из трех четко определенных методов, указывающих, будут ли переменные с плавающей запятой сначала переведены в более точный формат в выражениях: FLT_EVAL_METHOD == 2указывает, что все внутренние промежуточные вычисления выполняются по умолчанию с высокой точностью (long double) там, где это возможно (например, 80-битное двойное расширение ), FLT_EVAL_METHOD == 1выполняет все внутренние промежуточные выражения с двойной точностью (если только операнд не является long double), тогда как FLT_EVAL_METHOD == 0указывает, что каждая операция оценивается только с точностью самого широкого операнда каждой операции. rator. Тип промежуточного результата для операндов заданной точности сведен в соседней таблице.

FLT_EVAL_METHOD == 2имеет тенденцию ограничивать риск ошибок округления, влияющих на численно нестабильные выражения (см. Обоснование дизайна IEEE 754 ) и является разработанным методом по умолчанию для оборудования x87, но дает неинтуитивное поведение для неосторожного пользователя; FLT_EVAL_METHOD == 1изначально использовался метод оценки по умолчанию в KR C, который увеличил все числа с плавающей запятой до удвоения в выражениях; и 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, ведет к специфичному для компилятора поведению; такие несоответствия не допускаются в компиляторах, соответствующих C99 (приложение F).

Пример

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

1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 9 double compute_fn (double z) // [1] 10 {11 #pragma STDC FENV_ACCESS ON // [2 ] 12 13 утверждение (FLT_EVAL_METHOD == 2); // [3] 14 15 if (isnan (z)) // [4] 16 put («z не является числом»); 17 18 if (isinf (z)) 19 put («z бесконечно»); 20 21 long double 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] 22 23 feclearexcept (FE_DIVBYZERO); // [7] 24 25 булевых поднято = fetestexcept (FE_OVERFLOW); // [8] 26 27 if (поднят) 28 put ("Непредвиденное переполнение."); 29 30 возврат р; 31} 32 33 int main (void) 34 {35 #ifndef __STDC_IEC_559__ 36 put («Предупреждение: __STDC_IEC_559__ не определено. Плавающая точка IEEE 754 не полностью поддерживается.»); // [9] 37 #endif 38 39 #pragma STDC FENV_ACCESS ON 40 41 #ifdef TEST_NUMERIC_STABILITY_UP 42 fesetround (FE_UPWARD); // [10] 43 #elif TEST_NUMERIC_STABILITY_DOWN 44 fesetround (FE_DOWNWARD); 45 #endif 46 47 printf ("%. 7g \ n", compute_fn (3.0)); 48 printf ("%. 7g \ n", compute_fn (NAN)); 49 50 возврат 0; 51}

Сноски:

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

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

#if __STDC_VERSION__>= 199901L / * "inline" - ключевое слово * / #else # define inline static #endif
Реализации

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

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

Дальнейшая работа

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

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

См. Также
  • значок Портал компьютерного программирования
Ссылки
Дополнительная литература
Внешние ссылки
Предшествующие. C89 / C90 / "ANSI C" язык C стандартыПреемник. C11

Последняя правка сделана 2021-05-13 09:55:31
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте