C99 - C99
Редакции языка C |
---|
K&R C • ANSI C • C99 • C11 • C17 • C2x |
Этот отсутствует информация о _Pragma (), FP_CONTRACT, CX_LIMITED_RANGE.Ноябрь 2020) ( |
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 решил, что для компиляторов важнее диагностировать непреднамеренное упущение спецификатора типа, чем молча обрабатывать унаследованный код, основанный на неявном int
. На практике компиляторы могут отображать предупреждение, а затем предполагать int
и продолжаем перевод программы.
C99 представил несколько новых функций, многие из которых уже были реализованы в виде расширений в нескольких компиляторах:[4]
- встроенные функции
- смешанные декларации и код: Переменная объявление больше не ограничивается областью файла или началом составного оператора (блока), что упрощает статическая форма единого назначения
- несколько новых типы данных, включая
длинный длинный int
, необязательные расширенные целочисленные типы, явный логический тип данных, асложный
тип для представления сложные числа - массивы переменной длины (хотя впоследствии был переведен в C11 к условной функции, которую реализации не обязаны поддерживать)
- гибкие элементы массива
- поддержка однострочного Комментарии начиная с
//
, как в BCPL, C ++ и Ява - новые библиотечные функции, такие как
snprintf
- новый заголовки, Такие как
<stdbool.h >
,<complex.h >
,<tgmath.h >
, и<inttypes.h >
- типовые математические (макро) функции, в
<tgmath.h>
, которые выбирают математическая библиотека функция основанный наплавать
,двойной
, или жедлинный двойной
аргументы и т. д. - улучшенная поддержка IEEE с плавающей точкой
- назначенные инициализаторы (например, инициализация структуры по именам полей:
структурная точка p = {.x = 1, .y = 2};
)[5] - составные литералы (например, можно создавать структуры в вызовах функций:
функция ((структура x) {1, 2})
)[6] - Поддержка для вариационные макросы (макросы с переменным количеством аргументов)
ограничивать
квалификация допускает более агрессивный код оптимизация, устраняя преимущества доступа к массиву во время компиляции, которыми ранее обладал FORTRAN по ANSI C[7]- универсальные имена символов, которые позволяют пользовательским переменным содержать символы, отличные от стандартного набора символов
- ключевое слово
статический
в индексах массивов в объявлениях параметров[8]
Части стандарта C99 включены в текущую версию C ++ стандарт, включая целочисленные типы, заголовки и библиотечные функции. Массивы переменной длины не входят в число этих включенных частей, потому что C ++ Стандартная библиотека шаблонов уже включает аналогичные функции.
Поддержка IEEE 754 с плавающей запятой
Основной особенностью C99 является поддержка числовых значений, и в частности поддержка доступа к функциям IEEE 754-1985 (также известный как IEC 60559) плавающая точка аппаратное обеспечение, присутствующее в подавляющем большинстве современных процессоров (определено в «Приложении F IEC 60559 арифметика с плавающей запятой»). Платформы без оборудования IEEE 754 также могут реализовать это в программном обеспечении.[2]
На платформах с плавающей запятой IEEE 754:
плавать
определяется как IEEE 754 одинарная точность,двойной
определяется как двойная точность, идлинный двойной
определяется как IEEE 754 повышенная точность (например, Intel 80-бит двойной расширенный точность на x86 или же x86-64 платформы) или какой-либо четверная точность где доступно; в противном случае это двойная точность.- Четыре арифметических операции и квадратный корень правильно округлены в соответствии с определением IEEE 754.
FLT_EVAL_METHOD плавать двойной длинный двойной 0 плавать двойной длинный двойной 1 двойной двойной длинный двойной 2 длинный двойной длинный двойной длинный двойной - Оценка выражений должна выполняться одним из трех четко определенных методов, указывающих, будут ли переменные с плавающей запятой сначала переведены в более точный формат в выражениях:
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 для вычисления функции непрерывной дроби демонстрирует основные возможности:
1 #включают <stdio.h> 2 #включают <math.h> 3 #включают <float.h> 4 #включают <fenv.h> 5 #включают <tgmath.h> 6 #включают <stdbool.h> 7 #включают <assert.h> 8 9 двойной compute_fn(двойной z) // [1]10 {11 #pragma STDC FENV_ACCESS ON // [2]12 13 утверждать(FLT_EVAL_METHOD == 2); // [3]14 15 если (Иснан(z)) // [4]16 ставит("z не число");17 18 если (isinf(z))19 ставит("z бесконечно");20 21 длинный двойной р = 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 очищаться, кроме(FE_DIVBYZERO); // [7]24 25 bool поднятый = праздник, кроме(FE_OVERFLOW); // [8]26 27 если (поднятый)28 ставит(«Непредвиденное переполнение».);29 30 возвращаться р;31 }32 33 int главный(пустота)34 {35 #ifndef __STDC_IEC_559__36 ставит(«Предупреждение: __STDC_IEC_559__ не определено. Плавающая точка IEEE 754 не полностью поддерживается».); // [9]37 #endif38 39 #pragma STDC FENV_ACCESS ON40 41 #ifdef TEST_NUMERIC_STABILITY_UP42 fesetround(FE_UPWARD); // [10]43 #elif TEST_NUMERIC_STABILITY_DOWN44 fesetround(FE_DOWNWARD);45 #endif46 47 printf("% .7g п", compute_fn(3.0));48 printf("% .7g п", compute_fn(NAN));49 50 возвращаться 0;51 }
Сноски:
- Скомпилировать с помощью:
gcc -std=c99 -mfpmath=387 -o test_c99_fp -lm test_c99_fp.c
- Поскольку в этой функции используются флаги состояния IEEE 754, эта #pragma необходима, чтобы избежать неправильного изменения компилятором таких тестов при оптимизации. (Прагмы обычно определяются реализацией, но с префиксом
STDC
определены в стандарте C.) - C99 определяет ограниченное количество методов оценки выражений: текущий режим компиляции можно проверить, чтобы убедиться, что он соответствует предположениям, в соответствии с которыми был написан код.
- Особые значения, такие как NaN можно проверить и установить положительную или отрицательную бесконечность.
длинный двойной
определяется как IEEE 754 с двойным расширением или с четырехкратной точностью, если доступно. Использование более высокой точности, чем требуется для промежуточных вычислений, может минимизировать ошибка округления[11] (в typedefdouble_t
может использоваться для кода, переносимого под всемиFLT_EVAL_METHOD
с).- Основная функция, которую необходимо оценить. Хотя кажется, что некоторые аргументы этой непрерывной дроби, например 3,0, могут привести к ошибке деления на ноль, на самом деле функция четко определена в 3,0, и деление на 0 просто вернет + бесконечность, которая затем будет правильно приводят к конечному результату: IEEE 754 определен таким образом, чтобы не перехватывать такие исключения по умолчанию и спроектирован так, что их очень часто можно игнорировать, как в этом случае. (Если
FLT_EVAL_METHOD
определяется как 2, тогда все внутренние вычисления, включая константы, будут выполняться с длинной двойной точностью; еслиFLT_EVAL_METHOD
определяется как 0, то для обеспечения этого необходимы дополнительные меры, включая, возможно, дополнительные приведения и явное указание констант как long double.) - Поскольку поднятый флаг деления на ноль в этом случае не является ошибкой, его можно просто отклонить, чтобы сбросить флаг для использования в последующем коде.
- В некоторых случаях другие исключения могут быть расценены как ошибка, например, переполнение (хотя на самом деле может быть показано, что в данном случае этого не может произойти).
__STDC_IEC_559__
должен быть определен только в том случае, если "Арифметика с плавающей запятой МЭК 60559 Приложение F" полностью реализована компилятором и библиотекой C (пользователи должны знать, что этот макрос иногда определяется, а не должен).- Режим округления по умолчанию - округление до ближайшего (с правилом равного округления в полусредних случаях) для IEEE 754, но явная установка режима округления в сторону + и - бесконечности (путем определения
TEST_NUMERIC_STABILITY_UP
и т.д. в этом примере при отладке) может использоваться для диагностики числовой нестабильности.[12] Этот метод можно использовать, даже еслиcompute_fn ()
является частью отдельно скомпилированной двоичной библиотеки. Но в зависимости от функции числовые нестабильности не всегда обнаруживаются.
Обнаружение версии
Стандартный макрос __STDC_VERSION__
определяется со значением 199901L
чтобы указать, что доступна поддержка C99. Как и в случае с __STDC__
макрос для C90, __STDC_VERSION__
можно использовать для написания кода, который будет по-разному компилироваться для компиляторов C90 и C99, как в этом примере, который гарантирует, что в соответствии
доступен в любом случае (заменив его на статический
в C90, чтобы избежать ошибок компоновщика).
#if __STDC_VERSION__> = 199901L / * "inline" - ключевое слово * /#еще# определить встроенный статический#endif
Реализации
Большинство компиляторов C обеспечивают поддержку по крайней мере некоторых функций, представленных в C99.
Исторически, Microsoft медленно внедрял новые функции C в свои Visual C ++ инструменты, вместо этого сосредоточившись в основном на поддержке разработок в стандартах C ++.[13] Однако с появлением Visual C ++ 2013 Microsoft реализовала ограниченное подмножество C99, которое было расширено в Visual C ++ 2015.[14]
Компилятор | Уровень поддержки | Детали совместимости C99 |
---|---|---|
Желудь C / C ++ | Частичное | В официальной документации указано, что поддерживается «большинство» функций компилятора, а также «некоторые» функции библиотеки. |
AMD x86 Пакет компилятора Open64 | По большей части | Имеет поддержку C99, равную поддержке GCC.[15] |
cc65 | Частичное | Полный C89 и поддержка C99 не реализована, частично из-за ограничений платформы (Технология MOS 6502 ). Поддержка некоторых типов C99, таких как _Complex и 64-битных целых (long long), не планируется.[16] |
Ch | Частичное | Поддерживает основные функции C99.[17] |
Лязг | По большей части | Поддерживает все функции, кроме прагм C99 с плавающей запятой.[18] |
CompCert | По большей части | Сертифицированный компилятор, формально доказавший свою правильность. Поддерживает все функции, кроме комплексных чисел C99 и VLA, а также незначительные ограничения на операторы переключения (нет Устройство Даффа ).[19] |
анализатор | Полный | Поддерживает функции C99.[20] |
C ++ Builder | Только в 64-битном режиме, так как последний является вилкой CLang [нужна цитата ] | |
Компилятор Digital Mars C / C ++ | Частичное | Отсутствует поддержка некоторых функций, таких как <tgmath.h > и _Pragma.[21] |
GCC | По большей части | По состоянию на июнь 2014 г.[Обновить]расширенные идентификаторы, стандартные прагмы и поддержка операций с плавающей запятой IEEE 754 / IEC 60559 отсутствуют в основном GCC. Кроме того, некоторые функции (такие как расширенные целочисленные типы и новые библиотечные функции) должны предоставляться стандартной библиотекой C и выходят за рамки GCC.[22] Выпуски 4.6 и 4.7 GCC также обеспечивают такой же уровень соответствия.[23][24] Частичная поддержка IEEE 754, даже если оборудование совместимо: некоторые параметры компилятора могут потребоваться, чтобы избежать неправильной оптимизации (например, -std = c99 и -fsignaling-nans), но полная поддержка режимов направленного округления отсутствует даже при -frounding-math используется.[25] |
Программное обеспечение Green Hills | Полный | |
IBM C для AIX, V6 [26] и XL C / C ++ V11.1 для AIX [27] | Полный | |
IBM Rational логископ | Полный | До Logiscope 6.3 поддерживались только базовые конструкции C99. C99 официально поддерживается в Logiscope 6.4 и более поздних версиях.[28] |
Портлендская группа PGI C / C ++ | Полный | |
IAR Systems Встроенный верстак | По большей части | Не поддерживает UCN (универсальные имена символов). Компилятор для встроенных целей, таких как ARM, Coldfire, MSP430, AVR, AVR32, 8051, ... Нет целей x86. |
Компилятор Intel C ++ | По большей части [нужна цитата ] | |
Microsoft Visual C ++ | Частичное[14] | Visual C ++ 2012 и более ранние версии не поддерживали C99.[29][30][31] Visual C ++ 2013 реализует ограниченное подмножество C99, необходимое для компиляции популярных проектов с открытым исходным кодом.[32][33] Visual C ++ 2015 реализует стандартную библиотеку C99, за исключением любых функций библиотеки, которые зависят от функций компилятора, которые еще не поддерживаются компилятором (например, <tgmath.h > не реализовано).[14] Visual C ++ 2019 (16.6) добавляет дополнительную поддержку препроцессора, совместимого с C99.[34] |
Откройте Watcom | Частичное | Реализует наиболее часто используемые части стандарта. Однако они включаются только с помощью недокументированного переключателя командной строки «-za99». Три функции C99 были объединены как расширения C90, начиная с версии до версии 1.0: комментарии в стиле C ++ (//), гибкие элементы массива, конечная запятая, разрешенная в объявлении перечисления.[35] |
Пеллес С | Полный | Поддерживает все функции C99.[36] |
Портативный компилятор C | Частичное | Работаем над соответствием C99.[нужна цитата ] |
Солнечная студия | Полный[37] | |
В Комплект компилятора Amsterdam | Нет[нужна цитата ] | Интерфейс C99 в настоящее время исследуется.[нужна цитата ] |
Крошечный компилятор C | Частичное | Не поддерживает комплексные числа.[38][39] Поддерживаются массивы переменной длины, но не в качестве аргументов в функциях.[нужна цитата ]. Разработчики заявляют, что «TCC движется к полному соответствию ISOC99».[40] |
vbcc | Частичное |
Будущая работа
После ратификации стандарта C 1999 года рабочая группа по стандартам подготовила технические отчеты, в которых указывается улучшенная поддержка встроенной обработки, дополнительные типы символьных данных (Unicode поддержка) и библиотечные функции с улучшенными проверка границ. Продолжается работа над техническими отчетами, относящимися к десятичным плавающая точка, дополнительные математические специальные функции, и дополнительные распределение динамической памяти функции. Комитеты по стандартам C и C ++ совместно разрабатывают спецификации для резьбовой программирование.
Следующая версия стандарта C, C11, была ратифицирована в 2011 году.[41] Комитет по стандартам C принял руководящие принципы, ограничивающие принятие новых функций, которые не были протестированы существующими реализациями. Много усилий было потрачено на разработку модель памяти, чтобы уточнить точки последовательности и поддерживать резьбовой программирование.
Смотрите также
- C ++ 17, C ++ 14, C ++ 11, С ++ 03, C ++ 98, версии стандарта языка программирования C ++
- Совместимость C и C ++
- Технический отчет C ++ 1
- Плавающая точка, для дальнейшего обсуждения использования оборудования IEEE 754
Рекомендации
- ^ «ISO / IEC 9899: 1999 - Языки программирования - C». Iso.org. 8 декабря 2011 г.. Получено 8 апреля 2014.
- ^ а б http://grouper.ieee.org/groups/754/meeting-materials/2001-07-18-c99.pdf
- ^ «Стандарты - Использование коллекции компиляторов GNU (GCC)». Gcc.gnu.org. Получено 8 апреля 2014.
- ^ «Параметры диалекта C - Использование коллекции компиляторов GNU (GCC)». Gcc.gnu.org. 6 мая 2009 года. Получено 8 апреля 2014.
- ^ «Использование коллекции компиляторов GNU (GCC): назначенные инициализаторы». gnu.org. Получено 18 сентября 2019.
- ^ «Использование коллекции компиляторов GNU (GCC): составные литералы». gnu.org. Получено 31 января 2016.
- ^ Ульрих Дреппер (23 октября 2007 г.). «Что должен знать каждый программист о памяти». LWN.net. Получено 3 апреля 2015.
- ^ ISO / IEC 9899: 1999 спецификация, TC3 (PDF). п. 119, § 6.7.5.3 Деклараторы функций (включая прототипы) пункт 7.
- ^ Дуг Прист (1997). «Различия между реализациями IEEE 754».
- ^ Джек Вур (1 ноября 1997 г.). «Разговор с Уильямом Каханом».
- ^ Уильям Кахан (11 июня 1996 г.). «Пагубное влияние компьютерных тестов на прикладную математику, физику и химию» (PDF).
- ^ Уильям Кахан (11 января 2006 г.). «Насколько бесполезны бездумные оценки округления в вычислениях с плавающей запятой?» (PDF).
- ^ Питер Брайт (29 июня 2013 г.). «C99, наконец, признал, что Microsoft прокладывает свой путь к C ++ 14». Ars Technica. Получено 9 января 2015.
- ^ а б c Бреннер, Пат. «Что нового для Visual C ++ в Visual Studio 2015». Сеть разработчиков Microsoft. Получено 27 апреля 2015.
- ^ "x86 Open64". Developer.amd.com. 1 апреля 1989 г. Архивировано с оригинал 3 мая 2009 г.. Получено 8 июн 2009.
- ^ "cc65 - бесплатный компилятор C для систем на базе 6502". Получено 14 сентября 2011.
- ^ "Возможности интерпретатора C / C ++ Ch C99". SoftIntegration, Inc. 15 февраля 2008 г.. Получено 15 февраля 2008.
- ^ "Руководство пользователя компилятора Clang". Получено 14 октября 2017.
- ^ "Документация по CompCert C и руководство пользователя v2.5". Получено 12 сентября 2015.
- ^ "домашняя страница libfirm". Получено 4 февраля 2014.
- ^ «Реализация языка C - Цифровой Марс». Получено 14 сентября 2011.
- ^ «Статус функций C99 в GCC». Free Software Foundation, Inc. 12 июня 2014 г.. Получено 25 августа 2014.
- ^ «Статус функций C99 в GCC 4.6». Free Software Foundation, Inc. 23 мая 2013 г.. Получено 23 мая 2013.
- ^ «Статус функций C99 в GCC 4.7». Free Software Foundation, Inc. 23 мая 2013 г.. Получено 23 мая 2013.
- ^ «Семантика математики с плавающей запятой в GCC». 20 июля 2018 г.. Получено 12 августа 2018.
- ^ «IBM C для AIX, V6.0 теперь поддерживает стандарт C99». Получено 31 января 2016.
- ^ «IBM - XL C / C ++ для AIX». Получено 31 января 2016.
- ^ «Поддержка IBM Rational Logiscope стандарта C99 - США». Получено 31 января 2016.
- ^ «Вопросы и ответы читателя: А как насчет VC ++ и C99?». Sutter’s Mill. Получено 31 января 2016.
- ^ «A.27 Использование массивов переменной длины C99». Microsoft. Получено 31 января 2016.
- ^ «Разработчики Microsoft для C99: используйте ISO C ++». InfoQ. Получено 31 января 2016.
- ^ «Поддержка библиотеки C99 в Visual Studio 2013». Microsoft. Получено 31 января 2016.
- ^ «Возможности, исправления и критические изменения C ++ 11/14 STL в VS 2013 - Блог группы разработчиков Visual C ++ - Домашняя страница сайта - Блоги MSDN». Blogs.msdn.com. 28 июня 2013 г.. Получено 8 апреля 2014.
- ^ «Объявление о полной поддержке препроцессора, совместимого с C / C ++, в MSVC». Microsoft. 27 марта 2020 г.. Получено 17 сентября 2020.
- ^ «Соответствие C99 в Open Watcom». Архивировано из оригинал 3 мая 2015 г.. Получено 25 сентября 2015.
- ^ "Обзор Pelles C". Январь 2013.
- ^ "Sun Studio 12: ознакомительные сведения о компиляторе C 5.9". Sun Microsystems, Inc. 31 мая 2007 г.. Получено 23 сентября 2012.
- ^ "Справочная документация по компилятору Tiny C". Получено 31 января 2016.
- ^ Согласно проекту Список дел комплексные типы - единственная отсутствующая функция C99. Массивы переменной длины были добавлены в TCC 0.9.26 [1]
- ^ «TCC: Tiny C Compiler». Получено 31 января 2016.
- ^ «Стандарты - Использование коллекции компиляторов 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
внешняя ссылка
Предшествует C89 / C90 / "ANSI C" | Язык C стандарты | Преемник C11 |