Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Обложка стандарта C99

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

История [ править ]

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

Дизайн [ править ]

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

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

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

  • встроенные функции
  • смешанные объявления и код: объявление переменной больше не ограничивается областью файла или началом составного оператора (блока), что упрощает статическую форму одиночного присваивания
  • несколько новых типов данных , включая long long intнеобязательные расширенные целочисленные типы, явный логический тип данных и complexтип для представления комплексных чисел
  • массивы переменной длины (хотя впоследствии в C11 они были отнесены к условной функции, которую реализации не обязаны поддерживать)
  • гибкие элементы массива
  • поддержка однострочных комментариев, начинающихся с //, как в BCPL , C ++ и Java
  • новые библиотечные функции, такие как snprintf
  • новые заголовки , такие как , , , и<stdbool.h><complex.h><tgmath.h><inttypes.h>
  • Тип унифицированной математика (макро) функция, в <tgmath.h>, которые используются для выбора математической библиотеки функции , основанную на float, doubleили long doubleаргументов, и т.д.
  • улучшенная поддержка плавающей запятой IEEE
  • назначенные инициализаторы (например, инициализировать структуру по именам полей: struct point p = { .x = 1, .y = 2 };) [5]
  • составные литералы (например, можно построить структуры в вызовах функций: function((struct x) {1, 2})) [6]
  • поддержка вариативных макросов (макросов с переменным количеством аргументов)
  • restrictквалификация позволяет более агрессивно оптимизировать код , устраняя преимущества доступа к массиву во время компиляции, ранее имевшиеся у FORTRAN по сравнению с ANSI C [7]
  • универсальные имена символов, которые позволяют пользовательским переменным содержать символы, отличные от стандартного набора символов
  • ключевое слово staticв индексах массива в объявлениях параметров [8]

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

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

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

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

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

FLT_EVAL_METHOD == 2имеет тенденцию ограничивать риск ошибок округления, влияющих на численно нестабильные выражения (см. обоснование разработки IEEE 754 ), и является методом, разработанным по умолчанию для оборудования x87 , но приводит к неинтуитивному поведению для неосторожного пользователя; [9] FLT_EVAL_METHOD == 1 был методом оценки по умолчанию, первоначально использовавшимся в K&R 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 с плавающей запятой, что приводило к специфичному для компилятора поведению; [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>double  compute_fn ( double  z )  // [1]{ #pragma STDC FENV_ACCESS ON // [2] утверждать ( FLT_EVAL_METHOD  ==  2 );  // [3] if  ( isnan ( z ))  // [4] кладет ( "z не число" ); если  ( isinf ( z )) put ( "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] если  ( поднят ) ставит ( "Непредвиденные переполнение." ); return  r ;}int  main ( пусто ){ #ifndef __STDC_IEC_559__ ставит ( «Внимание: __STDC_IEC_559__ не определен IEEE 754 с плавающей точкой не поддерживается полностью.» );  // [9] #endif #pragma STDC FENV_ACCESS ON #ifdef TEST_NUMERIC_STABILITY_UP fesetround ( FE_UPWARD );  // [10] #elif TEST_NUMERIC_STABILITY_DOWN 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 -lm test_c99_fp.c
  2. Поскольку в этой функции используются флаги состояния IEEE 754, эта #pragma необходима, чтобы избежать неправильного изменения компилятором таких тестов при оптимизации. (Прагмы обычно определяются реализацией, но префиксы с префиксом STDCопределены в стандарте C.)
  3. C99 определяет ограниченное количество методов оценки выражений: текущий режим компиляции можно проверить, чтобы убедиться, что он соответствует предположениям, в соответствии с которыми был написан код.
  4. Специальные значения, такие как NaN и положительная или отрицательная бесконечность, могут быть проверены и установлены.
  5. long doubleопределяется как IEEE 754 с двойным расширением или с четырехкратной точностью, если доступно. Использование более высокой точности, чем требуется для промежуточных вычислений, может минимизировать ошибку округления [11] ( 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__ должен быть определен только в том случае, если "Арифметика с плавающей запятой МЭК 60559 Приложение F" полностью реализована компилятором и библиотекой 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 # define 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 принял руководящие принципы, ограничивающие принятие новых функций, которые не были протестированы существующими реализациями. Много усилий было потрачено на разработку модели памяти , чтобы прояснить точки последовательности и поддержать многопоточное программирование.

См. Также [ править ]

  • C ++ 17 , C ++ 14 , C ++ 11 , C ++ 03 , C ++ 98 , версии стандарта языка программирования C ++
  • Совместимость C и C ++
  • Технический отчет C ++ 1
  • Плавающая точка , для дальнейшего обсуждения использования оборудования IEEE 754.

Ссылки [ править ]

  1. ^ «ISO / IEC 9899: 1999 - Языки программирования - C» . Iso.org. 8 декабря 2011 . Проверено 8 апреля 2014 года .
  2. ^ a b http://grouper.ieee.org/groups/754/meeting-materials/2001-07-18-c99.pdf
  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. ^ Ulrich Drepper (23 октября 2007). «Что должен знать каждый программист о памяти» . LWN.net . Проверено 3 апреля 2015 года .
  8. ^ ISO / IEC 9899: 1999 спецификация, TC3 (PDF) . п. 119, § 6.7.5.3 Деклараторы функций (включая прототипы) п. 7.
  9. Дуг Прист (1997). «Различия между реализациями IEEE 754» .
  10. ^ Джек Woehr (1 ноября 1997). «Разговор с Уильямом Каханом» .
  11. Уильям Кахан (11 июня 1996 г.). «Пагубное влияние компьютерных тестов на прикладную математику, физику и химию» (PDF) .
  12. Уильям Кахан (11 января 2006 г.). «Насколько бесполезны бездумные оценки округления в вычислениях с плавающей запятой?» (PDF) .
  13. Питер Брайт (29 июня 2013 г.). «C99 наконец признал, что Microsoft прокладывает свой путь к C ++ 14» . Ars Technica . Проверено 9 января 2015 года .
  14. ^ a b c Бреннер, Пат. «Что нового для Visual C ++ в Visual Studio 2015» . Сеть разработчиков Microsoft . Проверено 27 апреля 2015 года .
  15. ^ "x86 Open64" . Developer.amd.com. 1 апреля 1989. Архивировано из оригинала 3 мая 2009 года . Проверено 8 июня 2009 года .
  16. ^ "cc65 - бесплатный компилятор C для систем на базе 6502" . Проверено 14 сентября 2011 года .
  17. ^ "Особенности интерпретатора C / C ++ Ch C99" . SoftIntegration, Inc. 15 февраля 2008 . Проверено 15 февраля 2008 года .
  18. ^ "Руководство пользователя компилятора Clang" . Проверено 14 октября 2017 года .
  19. ^ "CompCert C Documentation and User Manual v2.5" . Проверено 12 сентября 2015 года .
  20. ^ "Домашняя страница libfirm" . Проверено 4 февраля 2014 года .
  21. ^ "Реализация языка C - Цифровой Марс" . Проверено 14 сентября 2011 года .
  22. ^ «Статус функций C99 в GCC» . Фонд свободного программного обеспечения, Inc. 12 июня 2014 . Проверено 25 августа 2014 года .
  23. ^ «Статус функций C99 в GCC 4.6» . Фонд свободного программного обеспечения, Inc. 23 мая 2013 . Проверено 23 мая 2013 года .
  24. ^ «Статус функций C99 в GCC 4.7» . Фонд свободного программного обеспечения, Inc. 23 мая 2013 . Проверено 23 мая 2013 года .
  25. ^ «Семантика математики с плавающей точкой в ​​GCC» . 20 июля 2018 . Проверено 12 августа 2018 .
  26. ^ «IBM C для AIX, V6.0 теперь поддерживает стандарт C99» . Проверено 31 января 2016 года .
  27. ^ "IBM - XL C / C ++ для AIX" . Проверено 31 января 2016 года .
  28. ^ «Поддержка IBM Rational Logiscope для стандарта C99 - США» . Проверено 31 января 2016 года .
  29. ^ "Читатель, вопросы и ответы: А как насчет VC ++ и C99?" . Саттерс Милл . Проверено 31 января 2016 года .
  30. ^ «A.27 Использование массивов переменной длины C99» . Microsoft . Проверено 31 января 2016 года .
  31. ^ «Разработчики Microsoft для C99: используйте ISO C ++» . InfoQ . Проверено 31 января 2016 года .
  32. ^ «Поддержка библиотеки C99 в Visual Studio 2013» . Microsoft . Проверено 31 января 2016 года .
  33. ^ «Возможности C ++ 11/14 STL, исправления и критические изменения в VS 2013 - Блог группы разработчиков Visual C ++ - Домашняя страница сайта - Блоги MSDN» . Blogs.msdn.com. 28 июня 2013 . Проверено 8 апреля 2014 года .
  34. ^ «Объявление о полной поддержке препроцессора, совместимого с C / C ++, в MSVC» . Microsoft. 27 марта 2020 . Проверено 17 сентября 2020 года .
  35. ^ «Соответствие C99 в Open Watcom» . Архивировано из оригинала 3 мая 2015 года . Проверено 25 сентября 2015 года .
  36. ^ "Обзор Pelles C" . Январь 2013.
  37. ^ "Sun Studio 12: C Compiler 5.9 Readme" . Sun Microsystems, Inc. 31 мая 2007 . Проверено 23 сентября 2012 года .
  38. ^ "Справочная документация по крошечному компилятору 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 года .

Дальнейшее чтение [ править ]

  • Ченг, Гарри (1 марта 2002 г.). «C99 и числовые вычисления» . Журнал доктора Добба .
  • Зеебах, Питер (24 марта 2004 г.). «Разработка с открытым исходным кодом с использованием C99» . developerWorks . IBM .
  • «Окончательная версия стандарта C99 с исправлениями TC1, TC2 и TC3, отформатированная как черновик» (PDF) . (3,61 МБ)
  • Обоснование международного стандарта - Языки программирования - Версия C 5.10 , апрель 2003 г., Обоснование для C99

Внешние ссылки [ править ]

  • Новые возможности C9X
  • Особенности C99