Які найкорисніші нові функції в C99? [зачинено]


78

C99 існує більше 10 років, але підтримка для нього йде повільно, тому більшість розробників дотримуються C89. Навіть сьогодні я часом злегка здивований, коли натрапляю на функції C99 в коді C.

Тепер, коли більшість основних компіляторів підтримують C99 (MSVC є помітним винятком, а деякі вбудовані компілятори також відстають), я вважаю, що розробники, які працюють з C, мабуть, повинні знати про те, які функції C99 доступні для них. Деякі функції - це просто загальні ознаки, які ніколи раніше не були стандартизовані ( snprintfнаприклад,) або знайомі з C ++ (гнучке розміщення змінної декларації або однорядкові //коментарі), але деякі нові функції були вперше представлені в C99 і є незнайомий багатьом програмістам.

Які найновіші функції C99 ви знайдете?

Для довідки - стандарт C99 (позначений як проект, але, наскільки мені відомо, ідентичний оновленому стандарту), перелік нових функцій та стан реалізації GCC C99 .

Будь ласка, одна функція на відповідь; не соромтеся залишати кілька відповідей. Запропоновано короткі приклади коду, що демонструють нові функції.


2
У C99 повинна бути подібна вікі для функцій, які люди ненавидять !
Alok Singhal

Ну, було питання про шкідливі або непідтримувані функції C99 stackoverflow.com/questions/1898890/…
Брайан Кемпбелл

Дякую. Вам слід змінити текст посилання, щоб вказати, що це чернетка, а не фактичний стандарт, і посилання на n1256, поки ви в ньому :-). До речі, дивлячись на gcc.gnu.org/c99status.html , я б не сказав, що більшість C99 підтримується gcc. І оскільки gcc є одним із найбільш часто використовуваних компіляторів C, ...
Alok Singhal

2
Зауважте, що на вбудованій процесорній арені C99 все ще може бути недостатньо підтримуваною.
Крейг МакКвін

1
@Alok Я б назвав такий рівень підтримки більшістю функцій; Я гадаю, це залежить від того, як ви це визначаєте, але я думаю, що більшість важливих функцій, якими люди хочуть користуватися, підтримуються, залишаючи осторонь кілька бібліотечних питань. @Craig Fair досить додав застереження щодо вбудованих компіляторів.
Брайан Кемпбелл

Відповіді:


77

Я так звик друкувати

в C ++, що це болісно використовувати компілятор, який не є C99, де я змушений сказати


44
Крім того, це звужує область дії змінної int, що завжди добре ^^
helpermethod

Це теж мій вибір.
figurassa

2
@Oliver <sarcasm> але потім інструкції sub esp, 4та add esp, 4видаляються! </sarcasm>
Коул Джонсон

72

stdint.h, що визначає int8_t, uint8_tтощо. Більше не потрібно робити непереносимих припущень про те, наскільки широкі ваші цілі числа.


19
Найкраща шістнадцяткова фраза з DE: AD: BE: EF: CA: FE.
Кевін Л.

Що повинен означати декафбад?
Pacerier

5
@Pacerier Це просто довільна шістнадцяткова константа, яка використовується для ілюстрації прикладу. Але для цінності гумору це означає "погано з кофеїном", що означає, що кава без кофеїну поступається справжній.
Брайан Кемпбелл,

5
гаразд, я не можу пов'язати їх гумор ...
Пейс'єр

66

Я думаю, що нові механізми ініціалізації надзвичайно важливі.

Добре - не переконливий приклад, але позначення є точним. Ви можете ініціалізувати певні елементи масиву та конкретні члени структури.

Можливо, кращим прикладом може бути такий - хоча я б визнав, що це не надзвичайно вагомо:


6
Це переконлива демонстрація. Існує величезна кількість таблиць enum з відповідними таблицями рядків.
u0b34a0f6ae

5
@ColeJohnson: Якщо ви уважно подивитесь на другий приклад, то помітите, що ініціалізатори перелічені не в порядку, але працюватимуть правильно. Цього не можна зробити просто за допомогою дефінітів. Перший приклад ініціалізує лише індекс 4 масиву; що теж не можна зробити просто за допомогою дефінітів.
Джонатан Леффлер

2
Слід також зазначити, що використання одного і того ж індексу більше одного разу замінить перше використання на друге - див. Моє запитання тут, наприклад: stackoverflow.com/questions/16742467/…
johnny

51

Масиви змінної довжини:


3
Ви справді думаєте, що масиви VLA такі чудові? C11 робить їх необов’язковими.
Z бозон

3
Тільки не забудьте застосувати санітарію введення, щоб запобігти переповненню стека (або пошкодженню стека, якщо x від’ємне):if (x < 0) x = 0; else if (x > 1024) x = 1024;
Ендрю Д'Аддезіо

51

Підтримка однорядкових коментарів, що починаються з //.


7
+1 ВСІ компілятори, яких я знаю, вже підтримують це. Прийшов час, це згадується в стандарті.
slebetman

41

Можливість оголошувати змінні в місцях, відмінних від початку блоку.


2
Я не так захоплююсь цим. На мій погляд, змінні слід не лише включати в область дії, коли це потрібно, але й вилучати з області, коли це не потрібно. Змінні в середині блоку майже незмінно зависають за обсягом довше, ніж слід.
supercat

5
@supercat ви б вважали за краще , int a; int b; a = f(); b = g();щоб int a = f(); int b = g();? Оголошення змінної близько до місця її ініціалізації є величезним для зменшення помилок.
Райан Хейнінг,

@RyanHaining: Альтернативно, створіть вкладений блок обсягу (я б просто хотів, щоб був стандартний синтаксис, в якому говорилося, що "цей блок призначений лише для масштабування"; для цього можна легко використовувати нульовий макрос, але це здається трохи потворним.
supercat

@supercat Для цього існує стандартний синтаксис: /* this block is just for scoping */ { } /* scope */:)
alx

@CacahueteFrito: Я думаю if(1) /* Scoping block */ { }, це трохи краще, але більша проблема полягає в тому, що масштаб і контроль - це ортогональні поняття. Хоча бувають випадки, коли має сенс охоплювати речі всередині циклу, частіше корисно мати обсяг простору навколо циклу, а також буває багато випадків, коли код створює об'єкти, що містять значення, які будуть потрібні при створенні більше жили об'єкти, але ніколи після цього (наприклад , float dx=x2-x1, dy=y2-y1; float distance = sqrt(dx*dx+dy*dy);Там немає причин , ах і ау повинні повинні зберігатися в області видимості ..
SUPERCAT

36

Варіадичні макроси. Спрощує генерацію шаблонного коду з необмеженою кількістю аргументів.


34

snprintf() - серйозно, варто багато, щоб мати можливість робити безпечні відформатовані рядки.


1
Дуже правильно. Я збирався додати цю відповідь сам, якщо цього не зробив ніхто інший.
Брайан Кемпбелл

29

Складені літерали. Встановлення структур поштучно так '89;)

Ви також можете використовувати їх, щоб отримати покажчики на об'єкти з автоматичною тривалістю зберігання без оголошення непотрібних змінних, наприклад

відразу


Він повинен розподілити пам'ять у стеку для 4, так?
AlphaGoku

29

Гнучкі члени масиву.

6.7.2.1 Специфікатори структури та об'єднання

Як особливий випадок, останній елемент структури, що має більше одного іменованого члена, може мати неповний тип масиву; це називається ible вигідним членом масиву . За двома винятками, елемент fl exible масиву ігнорується. По-перше, розмір структури повинен дорівнювати зміщенню останнього елемента інакше ідентичної структури, яка замінює еластичний елемент масиву масивом невизначеної довжини) По-друге, коли a .(або->) Оператор має лівий операнд, який є (вказівником на) структуру з ible ексклюзивним елементом масиву та правим іменем операнда, який називає цей член, він поводиться так, ніби цей член був замінений найдовшим масивом (з тим же типом елемента), який не зробити структуру більшою за об’єкт, до якого здійснюється доступ; зміщення масиву повинно залишатися зміщенням елемента живого масиву, навіть якщо це буде відрізнятися від значення масиву заміни. Якщо цей масив не мав би елементів, він поводиться так, ніби мав один елемент, але поведінка не визначена, якщо робиться спроба отримати доступ до цього елемента або сформувати покажчик за ним.

Приклад:


2
+1 за нарешті виготовлення цього кошерного. Це є в коді коду сокета TCP / IP, який я коли-небудь бачив.
slebetman

Справді, я вважав би це набагато кошернішим, ніж звичайний фокус використання buf [1] і віднімання 1 від розміру malloc. Фокус може бути загальним, але я розглядав би його як невизначену поведінку (належним чином було б використовувати buf [MAX_SIZE] і віднімати MAX_SIZE від розміру malloc), оскільки згенерований компілятором код індексації може залежати від сприйнятого розміру buf [].
supercat

25

Тип буля.

Тепер ви можете зробити щось подібне:

надрукує


2
той, хто думав про це, є чисто геніальним
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

Ні, boolв C99 примушує значення, присвоєне змінній, завжди бути 1 або 0. Ось чому ви повинні бути обережними, якщо у вас є код, який працює на компіляторі C99 і на старішому з "імітованим" boolтипом. Використання !!зробить це портативним. v = !!5;має однакову семантику, але не настільки читабельний.
Патрік Шлютер,

чи буде друкувати 1 при присвоєнні парного числа, такого як 6?
phuclv

Так. Будь-яке ненульове значення буде замінено на 1.
Патрік Шлютер,

18

Підтримка inlineфункцій.


На практиці GCC зазвичай ігнорує ключове слово inline, вирішуючи, які функції вбудовувати, і автоматично вбудовує речі на основі власної евристики, якщо ви не змусите його робити інше.
daf

7
daf: inlineвсе-таки допомагає, оскільки дозволяє визначити функцію в декількох одиницях перекладу - так що ви можете помістити її у заголовочний файл, що надає можливості вбудовування між модулями.
кафе

@dafinline __attribute__((force_inline))
Cole Johnson

18

Складені літерали, вже згадані, але ось мій переконливий приклад:

Це чіткий спосіб ініціалізації даних, навіть якщо вони знаходяться в купі. Немає можливості забути щось нульовою ініціалізацією.



15

Підтримка послідовності вихідної послідовності Unicode:

Або навіть буквальні символи Unicode:

(примітка: може не працювати залежно від вашої мови; портативна підтримка різних кодувань займе більше роботи, ніж це)


12

Шістнадцяткові константи з плаваючою комою ( 0x1.8p0f) та специфікатори перетворення ( %a, %A). Якщо ви часто маєте справу з числовими деталями низького рівня, це величезне покращення порівняно з десятковими літералами та перетвореннями.

Вони позбавляють вас від турбот щодо округлення при введенні констант для алгоритму і надзвичайно корисні для налагодження коду з плаваючою комою низького рівня.


3
Так, я нещодавно використовував їх, намагаючись пояснити комусь, як працюють числа з плаваючою комою в іншому запитанні щодо переповнення стека.
Брайан Кемпбелл,

9

Особисто мені подобається визнання IEC 60559: 1989 (двійкова арифметика з плаваючою точкою для мікропроцесорних систем) і набагато краща підтримка з плаваючою точкою.

У подібному ключі чудово мати налаштування та запитання режиму округлення з плаваючою точкою, перевірку чисел Nan / Infinity / subnormal тощо.


Ну, MS не любить цього робити
Cole Johnson

C насправді не дуже добре розроблений для концепції режимів округлення, оскільки вони означають, що математика з плаваючою точкою повинна розглядатися як така, що має побічні ефекти. Наявність чогось кращого, ніж семантика з плаваючою комою "сподівання на найкращого", корисна, але я не знаю, скільки реалізацій справді виконують усі вимоги Додатку F.
supercat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.