Это отсутствует информация о _Pragma (), FP_CONTRACT, CX_LIMITED_RANGE. Ноябрь 2020 г. ) ( |
Изменения языка C |
---|
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 плавать двойной длинный двойной 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 для вычисления функции непрерывной дроби демонстрирует основные возможности:
#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 ;}
Сноски:
- Скомпилировать с помощью:
gcc -std=c99 -mfpmath=387 -o test_c99_fp -lm test_c99_fp.c
- Поскольку в этой функции используются флаги состояния IEEE 754, эта #pragma необходима, чтобы избежать неправильного изменения компилятором таких тестов при оптимизации. (Прагмы обычно определяются реализацией, но префиксы с префиксом
STDC
определены в стандарте C.) - C99 определяет ограниченное количество методов оценки выражений: текущий режим компиляции можно проверить, чтобы убедиться, что он соответствует предположениям, в соответствии с которыми был написан код.
- Специальные значения, такие как NaN и положительная или отрицательная бесконечность, могут быть проверены и установлены.
long double
определяется как IEEE 754 с двойным расширением или с четырехкратной точностью, если доступно. Использование более высокой точности, чем требуется для промежуточных вычислений, может минимизировать ошибку округления [11] ( typedefdouble_t
может использоваться для кода, переносимого при всехFLT_EVAL_METHOD
s).- Основная функция, которую нужно оценить. Хотя кажется, что некоторые аргументы этой непрерывной дроби, например 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, как в этом примере, который гарантирует, что он 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]
Компилятор | Уровень поддержки | Детали совместимости 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 | Полный | До 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 Compiler Kit | Нет [ необходима ссылка ] | Интерфейс C99 в настоящее время исследуется. [ необходима цитата ] |
Крошечный компилятор C | Частичное | Не поддерживает комплексные числа. [38] [39] Поддерживаются массивы переменной длины, но не в качестве аргументов в функциях [ необходима ссылка ] . Разработчики заявляют, что «TCC движется к полному соответствию ISOC99». [40] |
vbcc | Частичное |
Будущая работа [ править ]
После ратификации стандарта 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.
Ссылки [ править ]
- ^ «ISO / IEC 9899: 1999 - Языки программирования - C» . Iso.org. 8 декабря 2011 . Проверено 8 апреля 2014 года .
- ^ a b 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 года .
- ^ Ulrich Drepper (23 октября 2007). «Что должен знать каждый программист о памяти» . LWN.net . Проверено 3 апреля 2015 года .
- ^ ISO / IEC 9899: 1999 спецификация, TC3 (PDF) . п. 119, § 6.7.5.3 Деклараторы функций (включая прототипы) п. 7.
- ↑ Дуг Прист (1997). «Различия между реализациями IEEE 754» .
- ^ Джек Woehr (1 ноября 1997). «Разговор с Уильямом Каханом» .
- ↑ Уильям Кахан (11 июня 1996 г.). «Пагубное влияние компьютерных тестов на прикладную математику, физику и химию» (PDF) .
- ↑ Уильям Кахан (11 января 2006 г.). «Насколько бесполезны бездумные оценки округления в вычислениях с плавающей запятой?» (PDF) .
- ↑ Питер Брайт (29 июня 2013 г.). «C99 наконец признал, что Microsoft прокладывает свой путь к C ++ 14» . Ars Technica . Проверено 9 января 2015 года .
- ^ a b 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 Documentation and User Manual v2.5" . Проверено 12 сентября 2015 года .
- ^ "Домашняя страница libfirm" . Проверено 4 февраля 2014 года .
- ^ "Реализация языка C - Цифровой Марс" . Проверено 14 сентября 2011 года .
- ^ «Статус функций C99 в GCC» . Фонд свободного программного обеспечения, Inc. 12 июня 2014 . Проверено 25 августа 2014 года .
- ^ «Статус функций C99 в GCC 4.6» . Фонд свободного программного обеспечения, Inc. 23 мая 2013 . Проверено 23 мая 2013 года .
- ^ «Статус функций C99 в GCC 4.7» . Фонд свободного программного обеспечения, 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?" . Саттерс Милл . Проверено 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 Compiler 5.9 Readme" . Sun Microsystems, Inc. 31 мая 2007 . Проверено 23 сентября 2012 года .
- ^ "Справочная документация по крошечному компилятору C" . Проверено 31 января 2016 года .
- ^ Согласно списку TODO проекта,единственной отсутствующей функцией 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
Внешние ссылки [ править ]
- Новые возможности C9X
- Особенности C99
Предшественник C89 / C90 / "ANSI C" | Стандарты языка C | Преемник C11 |