C99 был вокруг больше 10 лет, но поддержка его была медленным прибытием, таким образом, большинство разработчиков придерживалось C89. Даже сегодня я иногда мягко удивляюсь, когда я сталкиваюсь с функциями C99 в коде C.
Теперь, когда большинство главных компиляторов поддерживает C99 (MSVC, являющийся существенным исключением и некоторыми встроенными компиляторами, также отставая), я чувствую, что разработчики, которые работают с C, вероятно, должны знать о том, какие функции C99 доступны им. Некоторыми функциями являются просто типичные функции, которые никогда не стандартизировались прежде (snprintf
, например), или знакомы от C++ (гибкое размещение объявления переменной или одна строка //
комментарии), но некоторые новые возможности были сначала представлены в C99 и незнакомы многим программистам.
Что Вы находите самыми полезными новыми возможностями в C99?
Для ссылки, стандарт C99 (маркированный как проект, но идентичный обновленному стандарту, насколько я знаю), список новых возможностей и состояние реализации GCC C99.
Одна функция на ответ; не стесняйтесь оставлять несколько ответов. Примеры короткого кода, демонстрирующие новые возможности, поощряются.
Возможность объявления переменных в местах, отличных от начала блока.
Поддержка однострочных комментариев, начинающихся с //
.
Сложные буквы. Установка структур по члену такова, что '89 ;)
Можно также использовать их для получения указателей на объекты с автоматической длительностью хранения без объявления ненужных переменных, например
foo(&(int){ 4 });
insteand
int tmp = 4;
foo(&tmp);
Переменная длина массивов:
int x;
scanf("%d", &x);
int a[x];
for (int i = 0; i < x; ++i)
a[i] = i * i;
for (int i = 0; i < x; ++i)
printf("%d\n", a[i]);
Лично, мне нравится признание IEC 60559: 1989 (двоичная арифметика с плавающей точкой для микропроцессора Системы) и гораздо лучшая подставка с плавающей точкой.
В аналогичной вене, установке и запросе режима округления с плавающей точкой, проверка нан / бесконечности / субнормальных чисел и т. Д., Здорово иметь.
Это очень распространенная проблема при работе с классовым загрузчиком. Это часто наблюдается в приложениях Java EE, когда вы перестраиваете hibernate/cglib. Для получения дополнительной информации проверьте
-121--2316269-Кроме однозначной ясности, почему мы должны придерживаться: car.getSpeed () и car.setSpeed (55) когда это также может быть использовано: car.speed () и car.speed (55)
Поскольку во всех языках, с которыми я сталкивался, car.speed ()
и car.speed (55)
одинаковы с точки зрения синтаксиса. Просто глядя на них так, оба могут вернуть значение, что не верно для последнего, если он должен был быть установщиком.
Шестнадцатеричные плавающие константы точки ( 0x1.8p0f
) и спецификаторы преобразования (% a
, % A
). Если вы часто имеете дело с низкоуровневыми числовыми деталями, это огромное улучшение по сравнению с десятичными литералами и преобразованиями.
Они избавляют вас от беспокойства по поводу округления при задании констант для алгоритма и чрезвычайно полезны для отладки низкоуровневого кода с плавающей запятой.
Я думаю, что новые механизмы инициализатора чрезвычайно важны.
struct { int x, y; } a[10] = { [3] = { .y = 12, .x = 1 } };
ОК - не убедительный пример, но нотация является точной. Вы можете инициализировать определенные элементы массива и конкретных членов структуры.
Может быть, лучший пример будет это - хотя я признаю, что это не безумно убедительно:
enum { Iron = 26, Aluminium = 13, Beryllium = 4, ... };
const char *element_names[] =
{
[Iron] = "Iron",
[Aluminium] = "Aluminium",
[Beryllium] = "Beryllium",
...
};
Я так используется для ввода
for (int i = 0; i < n; ++i) { ... }
в C ++, что это боль в использовании Компилятор не C99, где я вынужден сказать
int i;
for (i = 0; i < n; ++i ) { ... }
Вариадические макросы. Облегчает генерацию кода котельной с неограниченным количеством аргументов.
Тип BoOL.
Теперь вы можете сделать что-то в этом роде:
bool v = 5;
printf("v=%u\n", v);
будет печать
1
snprintf()
- серьезно, это стоит того, чтобы иметь возможность делать безопасные отформатированные строки.
Впервые через внешнюю петлю внутренняя петля становится бесконечной петлей. Неважно, что происходит после этого. Там нет «после бесконечности».
-121--3758882- Диапазон (N)
начинается с 0
, а не 1
. 0 * J
всегда будет меньше n
.
Поддержка escape escape Unicode:
printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");
или четные, буквальные символы Unicode:
printf("日本語\n");
(Примечание: может не работать в зависимости от вашего языка; портативная поддержка для разных кодировщиков примет больше, чем это )
stdint.h
, который определяет int8_t
, uint8_t
и т. Д. Больше не нужно делать не портативные предположения о том, насколько широки есть ваши целые числа.
uint32_t truth = 0xDECAFBAD;
Гибкие члены массива.
6.7.2.1 Структура и союзные специфика
как особый случай, последний элемент структуры с более чем одним названным членом может иметь неполный тип массива; Это называется элементом массива . Благодаря двум исключением элементом массива FL ISPLACE игнорируется. Во-первых, размер структуры должен быть Равно к смещению последнего элемента иначе идентичной структуры, которая заменяет элемент MARAL ARM с массивом невырасных длины) вторым, когда
.
(или->
) Оператор имеет левый операнд (указатель на) структуру с элементом MARAL ARMAL и именами правильного операнда, который он ведет себя так, как если бы этот член был заменен самый длинный массив (с тем же типом элемента), который не сделает структуру больше, чем доступ к объекту; Смещение массива должно оставаться таким элементом MARAL MARY, даже если это будет отличаться от уровня замены массива. Если этот массив не будет никаких элементов, он ведет себя так, как будто у него был один элемент, но поведение не является, если какая-либо попытка доступа к этому элементу или для генерации указателя одного прошлого Это.
Пример:
typedef struct {
int len;
char buf[];
} buffer;
int bufsize = 100;
buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));