Эффективный C. Профессиональное программирование - Роберт С. Сикорд - E-Book

Эффективный C. Профессиональное программирование E-Book

Роберт С. Сикорд

0,0
10,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Мир работает на коде, написанном на C, но в большинстве учебных заведений программированию учат на Python или Java. Книга «Эффективный С для профессионалов» восполняет этот пробел и предлагает современный взгляд на C. Здесь рассмотрен C17, а также потенциальные возможности C2x. Издание неизбежно станет классикой, с его помощью вы научитесь писать профессиональные и надежные программы на C, которые лягут в основу устойчивых систем и решат реальные задачи.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 358

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Роберт С. Сикорд
Эффективный C. Профессиональное программирование

Научный редактор Р. Хазанский

Литературный редактор Н. Хлебина

Художник В. Мостипан

Корректоры Е. Павлович, Н. Смолич

Роберт С. Сикорд

Эффективный C. Профессиональное программирование. — СПб.: Питер, 2021.

ISBN 978-5-4461-1851-9

© ООО Издательство "Питер", 2021

Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.

Оглавление

Предисловие Паскаля Куока
Предисловие Олли Уайтхауса
Благодарности
Введение
Краткая история C
Стандарт C
Стандарт программирования CERT C
Для кого эта книга
Структура книги
От издательства
1. Знакомство с C
Разработка вашей первой программы на C
Редакторы и интегрированные среды разработки
Компиляторы
Переносимость
Резюме
2. Объекты, функции и типы
Объекты, функции, типы и указатели
Объявление переменных
Область видимости
Срок хранения
Выравнивание
Объектные типы
Функциональные типы
Производные типы
Теги
Квалификаторы типов
Упражнения
Резюме
3. Арифметические типы
Целые числа
Числа с плавающей запятой
Арифметическое преобразование
Резюме
4. Выражения и операции
Простое присваивание
Оценивание
Вызов функции
Операции инкремента и декремента
Приоритет и ассоциативность операций
Порядок вычисления
Операция sizeof
Арифметические операции
Битовые операции
Логические операции
Операции приведения типов
Условная операция
Операция _Alignof
Операции сравнения
Операции составного присваивания
Операция «запятая»
Арифметические операции с указателями
Резюме
5. Управляющая логика
Операторы-выражения
Составные операторы
Операторы выбора
Операторы итерирования
Операторы перехода
Упражнения
Резюме
6. Динамически выделяемая память
Срок хранения
Функции для управления памятью
Состояния памяти
Структуры с массивами произвольной длины
Другие виды динамически выделяемой памяти
Отладка проблем, связанных с выделением памяти
Упражнения
Резюме
7. Символы и строки
Символы
Строки
Функции для работы со строками
Резюме
8. Ввод/вывод
Стандартные потоки ввода/вывода
Открытие и создание файлов
Закрытие файлов
Чтение и запись символов и строк
Сброс потока на диск
Установка позиции в файле
Удаление и переименование файлов
Использование временных файлов
Чтение потоков форматированного текста
Чтение из двоичных потоков и запись в них
Резюме
9. Препроцессор (в соавторстве с Аароном Баллманом)
Процесс компиляции
Подключение файлов
Условная компиляция
Определение макросов
Резюме
10. Структура программы (в соавторстве с Аароном Баллманом)
Принципы компонентного представления
Исполняемые файлы
Компоновка
Структурирование простой программы
Сборка кода
Резюме
11. Отладка, тестирование и анализ
Утверждения
Параметры и флаги компиляторов
Отладка
Модульное тестирование
Статический анализ
Динамический анализ
Упражнения
Резюме
Список литературы
Об авторе
О соавторе
О научном редакторе
Рекомендуем прочитать

Посвящается моим внучкам, Оливии и Изабелле, а также другим молодым женщинам, которые станут учеными и инженерами, когда вырастут.

Предисловие Паскаля Куока

Впервые о Роберте Сикорде я услышал в 2008 году. В то время он уже был широко известен среди программистов на C своей работой над стандартом программированияCERT C и приложением K к стандарту C. Однако на тот момент прошло лишь пара лет с тех пор, как я, молодой и глупый, присоединился к проекту Frama-C, призванному гарантировать отсутствие нежелательного поведения в программах на C. Однажды мой интерес привлекла заметка об уязвимостях от CERT, согласно которой в кое-каких компиляторах C (в частности, в GCC) были убраны определенные проверки переполнения операций с плавающей запятой. Это решение имело причину: проверки были слишком примитивными и в случае переполнения приводили к неопределенному поведению.

Кроме того, компиляторы не были обязаны сообщать программисту о том, в чем состояла его ошибка, даже при максимальном уровне предупреждений. Неопределенное поведение в C может иметь серьезные последствия. Я решил исправить эту конкретную проблему. Одним из авторов той заметки был Роберт.

Эта книга научит вас программировать на C в современных условиях. Она поможет выработать хорошие привычки, которые не позволят вам сознательно или по небрежности использовать нежелательное поведение. Читатель должен понимать, что в объемных программах на языке C такое поведение может быть вызвано произвольным вводом, поэтому устранения обычных ошибок программистов может быть недостаточно!

В этой книге делается беспрецедентный упор на аспекты программирования на C, связанные с безопасностью. Я рекомендую к использованию все представленные в ней инструменты — они помогут вам избежать неопределенного поведения в ваших программах.

Паскаль Куок, главный научный сотрудник, TrustInSoft

Предисловие Олли Уайтхауса

Начав заниматься кибербезопасностью больше 25 лет назад, я изучал свое ремесло в основном путем поиска и использования небезопасного кода для работы с памятью в программах на C. Даже тогда этому классу уязвимостей было больше 20 лет. Работая в BlackBerry и перебирая горы отчетов о разборе кода, я мог воочию убедиться в том, насколько опасным может быть язык C для непосвященных. Теперь, уже в качестве технического директора транснациональной компании, предоставляющей профессиональные услуги по обеспечению кибербезопасности, я каждый день вижу, чем чреват плохо написанный код на C для нашего общества в цифровую эпоху.

Написание безопасного и профессионального кода на C до сих пор вызывает множество трудностей. Это может свести (и регулярно сводит) на нет многочисленные инновации в средствах защиты компиляторов и операционных систем. И хотя мы наблюдаем существенный прогресс в других современных языках, спрос на C по-прежнему растет, особенно в IoT и прочих средах с крайне ограниченными ресурсами.

Мнение Роберта о том, как профессионально и безопасно программировать на C, пользуется большим уважением. Уже больше десяти лет я советую его материал как клиентам, так и разработчикам внутри компании. Никто лучше него не научит вас писать код на C профессионально и среди прочего безопасно.

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

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

Олли Уайтхаус, технический директор, NCC Group

Благодарности

Хочу отметить всех тех, кто помогал в создании этой книги. Начну с Билла Поллока из No Starch Press, который неустанно убеждал меня написать книгу о C.

Благодарю Олли Уайтхауса и Паскаля Куока за отличные предисловия.

Аарон Баллман был прекрасным партнером в этом начинании. Помимо двух написанных им глав, он вычитывал весь текст (часто по несколько раз) и помогал мне решать как сложные, так и тривиальные проблемы.

Дуглас Гвин, заслуженный сотрудник научно-исследовательской лаборатории сухопутных войск США и почетный член комитета во главе стандарта C, помог вычитать все главы. Когда мои писательские навыки не соответствовали его ожиданиям, он подталкивал меня в правильном направлении.

Официальным научным редактором этой книги был мой хороший друг, Мартин Себор, поэтому за любые неточности, которые вы найдете, винить нужно именно его.

Помимо Аарона, Дага и Мартина отдельные главы вычитывали и другие уважаемые члены комитетов во главе стандартов C и C++, включая Джима Томаса, Томаса Кёппе, Нилла Дугласа, Тома Хонерманна и Жана Хейда Менеида. В число научных редакторов вошли мои коллеги из NCC Group: Ник Данн, Джонатан Линдси, Томаш Крамковски, Алекс Донисторп, Джошуа Доу, Каталин Висинеску, Аарон Адамс и Саймон Харраги. Техническими редакторами, не имеющими отношения к этим организациям, были Дэвид Леблан, Николас Уинтер, Джон Макфарлейн и Скотт Алоизио.

Кроме того, я хотел бы поблагодарить следующих профессионалов из No Starch, которые обеспечили выпуск качественного продукта: Элизабет Чедвик, Фрэнсис Со, Зака Лебовски, Энни Чой, Барбару Йен, Катрину Тейлор, Натали Глисон, Дерека Йи, Лорен Чун, Джину Редман, Шерон Уилки, Эмили Баттаглиа и Дапиндера Досанжа.

Введение

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

Создателям C не пришлось заходить настолько далеко; они спроектировали этот язык для работы с разнообразным вычислительным оборудованием и архитектурами, которые, в свою очередь, были ограничены законами физики и математики. Среда выполнения C находится непосредственно над аппаратным обеспечением, что делает ее более чувствительной к появлению оборудования с новыми возможностями, такими как векторные инструкции, эффективность которых в языках более высокого уровня обычно зависит от C.

Согласно рейтингу TIOBE, с 2001 года C остается либо самым популяр­ным, либо вторым по популярности языком программирования1. В 2019 году C стал языком года по версии TIOBE. Своей популярностью он, скорее всего, обязан нескольким основополагающим принципам, известным как дух C.

• Доверие к программисту. В целом язык C подразумевает, что вы знаете, что делаете, и позволяет вам делать это. Иногда такие действия имеют плохие последствия (например, когда вы не знаете, что делаете).

• Не следует мешать программисту делать то, что нужно. Язык C предназначен для системного программирования, поэтому должен уметь справляться с разнообразными низкоуровневыми задачами.

• Язык должен быть компактным и простым. Язык C достаточно сильно связан с оборудованием и является легковесным.

• Для выполнения любой операции должен быть лишь один способ.

• Язык должен быть быстрым, даже если его переносимость не гарантируется. Главный приоритет — возможность написания оптимально эффективного кода. А сделать его переносимым, безопасным и защищенным должны вы, программист.

Краткая история C

Язык программирования C был создан в 1972 году Деннисом Ритчи и Кеном Томпсоном в лабораториях Bell Labs. Позже Деннис Ритчи вместе с Брайаном Керниганом написал книгу The C Programming Language2 (K&R, 1988). В 1983 году Американский национальный институт стандартов (American National Standards Institute, ANSI) сформировал комитет X3J11 для разработки стандартной спецификации C, а в 1989 году стандарт C был ратифицирован как ANSI X3.159-1989, «Язык программирования C». Эта версия языка называется ANSI C или C89.

В 1990 году стандарт ANSI C был принят (без изменений) совместным комитетом Международной организации по стандартизации (International Organization for Standardization, ISO) и Международной электротехнической комиссией (International Electrotechnical Commission, IEC) и опубликован в качестве первой редакции стандарта C, C90 (ISO/IEC 9899:1990). Вторая редакция, C99, была опубликована в 1999 году (ISO/IEC 9899:1999), а третья, C11, — в 2011-м (ISO/IEC 9899:2011). Последняя (на момент написания этих строк), четвертая версия стандарта C вышла в 2018 году под названием C17 (ISO/IEC 9899:2018). В настоящий момент ISO/IEC работают над новейшей редакцией языка C, известной как C2x. Согласно опросу, проведенному компанией JetBrains в 2018 году, 52 % программистов на C используют C99, 36 % — C11, а 23 % работают с языком С для встраиваемых систем3.

Стандарт C

Стандарт C (ISO/IEC 9899:2018) описывает язык и является главным его авторитетом. Он может казаться неясным или даже непостижимым, но если вы хотите писать переносимый, безопасный и защищенный код, то вам необходимо понимать этот стандарт. Он предоставляет реализациям существенную степень свободы, позволяя им оставаться оптимально эффективными на разных аппаратных платформах. Реализация в терминологии стандарта C обозначает компилятор и имеет следующее определение:

«Определенный набор программного обеспечения, работающий в конкретной среде трансляции с определенными управляющими параметрами и отвечающий за трансляцию программ для конкретной  среды выполнения с поддержкой работы функций».

Из этого определения следует, что каждый компилятор с неким набором флагов командной строки и стандартной библиотекой C считается отдельной реализацией и что поведение разных реализаций может существенно различаться. Это видно на примере компилятора GNU GCC, который использует флаг -std= для определения стандарта языка; для данного параметра можно указывать такие значения, как c89, c90, c99, c11, c17, c18 и c2x. Значение по умолчанию зависит от версии компилятора. Если диалект C не был указан, то GCC 10 выбирает -std=gnu17, предоставляя тем самым расширения языка C. Если вам нужна переносимость, указывайте используемый вами стандарт. Для доступа к новым возможностям языка выбирайте последнюю спецификацию. Так, в 2019 году хорошим выбором был -std=c17.

Поскольку реализации могут вести себя по-разному и некоторые варианты их поведения являются неопределенными, то для того, чтобы понимать язык C, недостаточно писать простые тестовые программы4. При компиляции программы с помощью разных реализаций и на разных платформах ее поведение может меняться; расхождения могут возникать даже при использовании разных наборов флагов или стандартных библиотек C в рамках одной и той же реализации. Поведение кода может зависеть даже от разных версий компилятора. Стандарт C — единственный документ, описывающий, какие аспекты поведения гарантируются во всех реализациях, а какие могут варьироваться. Это в основном имеет последствия для разработки переносимых программ, но может сказаться и на защищенности и безопасности вашего кода.

Стандарт программирования CERT C

Руководя командой, отвечающей за безопасность кода в Институте программной инженерии при Университете Карнеги — Меллона, я написал справочное пособие The CERT® C Coding Standard, Second Edition: 98 Rules for Developing Safe, Reliable, and Secure Systems (Сикорд, 2014). В нем представлены примеры распространенных ошибок программирования на C и рекомендации по их исправлению. В данной книге некоторые из этих рекомендаций упоминаются в качестве источника подробной информации о тех или иных аспектах программирования на языке C.

Для кого эта книга

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

Книга содержит краткое введение в основы программирования на языке C, и после ее прочтения вы сможете писать программы, решать задачи и создавать рабочие системы. Здесь вы найдете понятные идиоматические примеры кода.

Вы познакомитесь с ключевыми концепциями программирования на C и научитесь писать высококачественный код, выполняя упражнения для каждой рассматриваемой темы. Вы узнаете, какие методики рекомендуются для разработки правильного и безопасного кода на C. Обновления и дополнительный материал можно найти на веб-странице этой книги https://www.nostarch.com/effective_c/ и на сайте http://www.robertseacord.com/. Если после прочтения вам захочется узнать больше о безопасном программировании на C, C++ или других языках, то, пожалуйста, ознакомьтесь с учебными курсами, которые предлагает NCC Group, пройдя по адресу https://www.nccgroup.trust/us/our-services/cyber-security/security-training/secure-coding/.

Структура книги

Данная книга начинается с вводной главы, которая охватывает ровно столько материала, сколько нужно, чтобы начать программировать. Затем мы сделаем шаг назад и исследуем главные составные элементы языка. В двух завершающих главах вы научитесь создавать из этих элементов настоящие системы и узнаете, как отлаживать, тестировать и анализировать написанный вами код. Главы выглядят следующим образом.

• В главе 1 «Знакомство с C» вы напишете простую программу на C, чтобы научиться использовать функцию main. Мы также рассмотрим несколько разных редакторов и компиляторов.

• В главе 2 «Объекты, функции и типы» изложены основы языка, такие как объявление переменных и функций. Вы также познакомитесь с принципами использования базовых типов.

• В главе 3 «Арифметические типы» рассказано о двух видах арифметических типов данных: целочисленных и с плавающей запятой.

• В главе 4 «Выражения и операции» вы узнаете, что такое операции5, и научитесь писать простые выражения для выполнения операций с объектами различных типов.

• В главе 5 «Управляющая логика» вы узнаете, как управлять порядком вычисления отдельных операторов. Для начала мы пройдемся по операторам-выражениям и составным операторам, которые описывают, какую работу нужно проделать. Затем рассмотрим три вида операторов, которые определяют, какие блоки кода выполняются и в каком порядке это происходит: операторы выбора, итерирования и перехода.

• В главе 6 «Динамически выделяемая память» вы узнаете, как память динамически выделяется в куче во время работы программы. Она нужна в ситуациях, когда до запуска кода неизвестно, сколько памяти ему понадобится.

• В главе 7 «Символы и строки» вы изучите различные кодировки, включая ASCII и Unicode, которые можно использовать для составления строк. Вы научитесь применять устаревшие функции из стандартной библиотеки C, интерфейсы с проверкой ограничений, а также API POSIX и Windows для представления и изменения строк.

• В главе 8 «Ввод/вывод» вы научитесь выполнять операции ввода/вывода для чтения и записи данных в терминалы и файловые системы. Ввод/вывод охватывает все пути, которыми информация попадает в программу и покидает ее. Без этого ваш код был бы бесполезным. Мы рассмотрим методики на основе стандартных потоков C и файловых дескрипторов POSIX.

• В главе 9 «Препроцессор» вы научитесь использовать препроцессор для подключения файлов, определения объектных и функциональных макросов, а также научитесь выполнять условную компиляцию кода в зависимости от свойств той или иной реализации.

• В главе 10 «Структура программы» вы научитесь разбивать свои программы на разные единицы трансляции, состоящие как из исходных, так и заголовочных файлов. Кроме того, вы узнаете, как скомпоновать несколько объектных файлов в единое целое, чтобы создать библиотеку или исполняемую программу.

• В главе 11 «Отладка, тестирование и анализ» описываются инструменты и методики для создания корректных программ, включая утверждение времени компиляции и выполнения, отладку, тестирование, статический и динамический анализ. Мы также обсудим, какие флаги компиляции рекомендуется использовать на разных этапах процесса разработки программного обеспечения.

Вам предстоит путешествие, по завершении которого вы станете новоиспеченным, но профессиональным программистом на C.

От издательства

Ваши замечания, предложения, вопросы отправляйте по электронному адресу [email protected] (издательство «Питер», компьютерная редакция).

Мы будем рады узнать ваше мнение!

На веб-сайте издательства www.piter.com вы найдете подробную информацию о наших книгах.

1Рейтинг TIOBE оценивает популярность языков программирования и находится по адресу https://www.tiobe.com/tiobe-index/. При его составлении учитываются количество квалифицированных программистов, учебных курсов и сторонних поставщиков для каждого языка. Этот рейтинг может пригодиться, если вы выбираете язык для изучения или разработки новой программной системы.

2Керниган Б., Ритчи Д. Язык программирования C. — М.: Вильямс, 2015.

3Подробности исследования ищите на сайте JetBrains: https://www.jetbrains.com/lp/devecosystem-2019/c/.

4Для этого есть замечательный инструмент Compiler Explorer: https://godbolt.org/.

5Английское слово operator, соответствующее термину «операция», иногда ошибочно переводят как «оператор». На самом деле (по историческим причинам) русский термин «оператор» соответствует английскому statement. Разговаривая с коллегами, скорее всего, вы будете использовать термин «оператор» как аналог англоязычного operator. — Примеч. пер.