Книга «Экстремальный Cи. Параллелизм, ООП и продвинутые возможности»

0 20

Книга «Экстремальный Cи. Параллелизм, ООП и продвинутые возможности»

Книга «Экстремальный Cи» научит вас пользоваться продвинутыми низкоуровневыми возможностями языка для создания эффективных систем, чтобы вы смогли стать экспертом в программировании на Cи.

Вы освоите директивы препроцессора, макрокоманды, условную компиляцию, указатели и многое другое. Вы по новому взглянете на алгоритмы, функции и структуры. Узнаете, как выжимать максимум производительности из приложений с ограниченными ресурсами.

В XXI веке Си остается ключевым языком в машиностроении, авиации, космонавтики и многих других отраслях. Вы узнаете как язык работает с Unix, как реализовывать принципы объектно-ориентированного программирования и разберетесь с многопроцессной обработкой.

Камран Амини научит вас думать, сомневаться и экспериментировать. Эта книга просто необходима для всех, кто хочет поднять знания Cи на новый уровень.

Последние нововведения в C

Прогресс не остановить. Язык программирования C является стандартом ISO, постоянно пересматриваемым в попытках сделать его лучше и привнести в него новые возможности. Но это не значит, что C становится проще; по мере развития языка в нем появляются новые и сложные концепции.

В этой главе я проведу краткий обзор новшеств C11. Как вы, наверное, знаете, стандарт C11 пришел на смену C99 и позже был заменен стандартом C18. Иными словами, C18 — самая последняя версия языка C, а C11 — предыдущая.

Интересно, что в C18 не появилось никаких новых возможностей; эта версия содержит лишь исправления ошибок, найденных в C11. Таким образом, все, что мы говорим о C11, фактически относится и к C18 — то есть к самому последнему стандарту C. Как видите, в C наблюдаются постоянные улучшения… вопреки мнению о том, что этот язык давно умер!

В данной главе будет представлен краткий обзор следующих тем:

  • способы определения версии C и написания кода, совместимого с разными версиями этого языка;
  • новые средства оптимизации и защиты исходного кода, такие как невозвращаемые функции и функции с проверкой диапазона;
  • новые типы данных и методы компоновки памяти;
  • функции с обобщенными типами;
  • поддержка Unicode в C11, которой не хватало в предыдущих стандартах этого языка;
  • анонимные структуры и объединения;
  • встроенная поддержка многопоточности и методов синхронизации в C11.
  • Начнем эту главу с обсуждения стандарта C11 и его нововведений.

    C11

    Разработка нового стандарта для технологии, которая используется на протяжении более 30 лет, — непростая задача. На C написаны миллионы (если не миллиарды!) строчек кода, и если вы хотите добавить новые возможности, то это нужно делать так, чтобы не затронуть существующий код. Новшества не должны создавать новые проблемы для имеющихся программ и не должны содержать ошибки. Такой взгляд на вещи может показаться идеалистическим, но это то, к чему нам следует стремиться.

    Приведенный ниже PDF-документ находится на сайте Open Standards и выражает обеспокоенность и мысли участников сообщества C перед началом работы над C11: «PDF-документ». Его полезно почитать, поскольку в нем собран опыт разработки нового стандарта для языка, на котором уже было написано несколько тысяч проектов.

    Мы будем рассматривать выпуск C11 с учетом всего вышесказанного. Будучи опубликованным впервые, стандарт C11 был далек от идеала и имел некоторые серьезные дефекты, со списком которых можно ознакомиться по адресу «PDF-документ».

    Через семь лет после выхода C11 был представлен стандарт C18, который должен был исправить недостатки предшественника. Стоит отметить, что C18 также неофициально называют C17, но это один и тот же стандарт. На странице, приведенной в ссылке выше, можно просмотреть перечень дефектов и их текущее состояние. Если состояние дефекта помечено как C17, то это значит, он был исправлен в рамках C18. Это показывает, насколько сложным и щепетильным может быть процесс формирования стандарта с таким большим количеством пользователей, как у языка C.

    В следующих разделах речь пойдет о новых возможностях C11. Но прежде, чем мы по ним пройдемся, необходимо убедиться в том, что у нас есть компилятор, совместимый с данным стандартом. Об этом мы позаботимся в следующем разделе.

    Определение поддерживаемой версии стандарта C

    На момент написания этих строк с момента выхода стандарта C11 прошло почти восемь лет. И потому было бы логично ожидать, что он уже поддерживается многими компиляторами. И это действительно так. Открытые компиляторы, такие как gcc и clang, имеют полную поддержку C11, но при необходимости могут переключаться на C99 и даже более ранние версии C. В данном разделе я покажу, как с помощью специального макроса определить версию C и в зависимости от нее использовать поддерживаемые возможности языка.

    Если ваш компилятор поддерживает разные версии стандарта C, то первым делом нужно проверить, какая версия является текущей. Каждый стандарт C определяет специальный макрос, позволяющий сделать это. До сих пор мы использовали gcc в Linux и clang в macOS. В gcc 4.1 C11 предоставляется в качестве одного из поддерживаемых стандартов.

    Рассмотрим следующий пример, чтобы понять, как на этапе выполнения узнать текущую версию стандарта C, используя уже определенный макрос (листинг 12.1).

    Листинг 12.1. Определение версии стандарта C (ExtremeC_examples_chapter12_1.c)

    Книга «Экстремальный Cи. Параллелизм, ООП и продвинутые возможности»

    Как видите, данный код может различать разные версии стандарта C. Чтобы продемонстрировать, как разные версии приводят к разному выводу, скомпилируем этот исходный код несколько раз с применением разных стандартов C, поддерживаемых компилятором.

    Чтобы заставить компилятор использовать определенный стандарт C, ему нужно передать параметр -std=CXX. Взгляните на следующую команду и на вывод, который она генерирует (терминал 12.1).

    Терминал 12.1. Компиляция примера 12.1 с помощью разных версий стандарта C

    Книга «Экстремальный Cи. Параллелизм, ООП и продвинутые возможности»

    Как видите, в новых компиляторах по умолчанию используется C11. В более старых версиях для включения C11 может понадобиться параметр -std. Обратите внимание на комментарии в начале файла. Я использовал многострочный формат, /*… */, вместо однострочного, //. Дело в том, что однострочные комментарии не поддерживались в стандартах, предшествовавших C99. Поэтому пришлось сделать комментарии многострочными, чтобы код компилировался со всеми версиями C.

    Удаление функции gets

    Из C11 была убрана знаменитая функция gets. Она была подвержена атакам с переполнением буфера, и в предыдущих версиях ее решили сделать нерекомендуемой. Позже она была удалена в рамках стандарта C11. Следовательно, старый исходный код, в котором используется эта функция, нельзя скомпилировать с помощью C11.

    Вместо gets можно использовать функцию fgets. Вот отрывок из справочной страницы gets в macOS.

    Соображения безопасности
    Функция gets() не подходит для безопасного использования. Ввиду отсутствия проверки диапазона и неспособности вызывающей программы надежно определить длину следующей входной строчки, применение этой функции позволяет недобросовестным пользователям вносить произвольные изменения в функциональность запущенной программы с помощью атаки переполнения буфера. В любых ситуациях настоятельно рекомендуется задействовать функцию fgets() (см. FSA).

    С полным содержанием статьи можно ознакомиться на сайте «Хабрахабр»:

    https://habr.com/ru/company/piter/blog/567302/

    Источник

    Оставьте ответ