Препроцессор
Препроцессор является обязательным компонентом компилятора языка Си. Вообще весь процесс компиляции программы на языке Си разбивается на три этапа:
Препроцессор обрабатывает исходный текст программы до ее непосредственной компиляции. Результатом работы препроцессора является полный текст программы, который передается на компиляцию в исполняемый файл.
Затем компилятор компилирует обработанный препроцессором исходный код в объектные файлы.
И на последнем этапе линкер (линковщик) объединяет (линкует) объектные файлы в один исполняемый файл или файл динамической библиотеки.
Для управления препроцессором применяются директивы, каждая из которых начинается с символа решетки # и располагается на отдельной строке. Препроцессор просматривает текст программы, находит эти директивы и должным образом обрабатывает их.
Мы можем использовать следующие директивы:
#define : определяет макрос или препроцессорный идентификатор
#undef : отменяет определение макроса или идентификатора
#ifdef : проверяет, определен ли идентификатор
#ifndef : проверяет неопределенности идентификатор
#include : включает текст из файла
#if : проверяет условие выражение (как условная конструкция if)
#else : задает альтернативное условие для #if
#endif : окончание условной директивы #if
#elif : задает альтернативное условие для #if
#line : меняет номер следующей ниже строки
#error : формирует текст сообщения об ошибке трансляции
#pragma : определяет действия, которые зависят от конкретной реализации компилятора
# : пустая директива, по сути ничего не делает
Рассмотрим основные из этих директив.
Директива #include. Включение файлов
Ранее уже использовалась директива #include . Эта директива подключает в исходный текст файлы. Она имеет следующие формы применения:
Например, если нам надо задействовать в приложении консольный ввод-вывод с помощью функций printf() или scanf() , то нам надо подключить файл «stdio.h», который содержит определение этих функций:
При выполнении этой директивы препроцессор вставляет текст файла stdio.h . Данный файл еще называется заголовочным. Заголовочные файлы содержат прототипы функций, определения и описания типов и констант и имеют расширение .h .
Поиск файла производится стандартных системных каталогах. Вообще есть стандартный набор встроенных заголовочных файлов, который определяется стандартом языка и которые мы можем использовать:
assert.h : отвечает за диагностику программ
complex.h : для работы с комплексными числами
ctype.h : отвечает за преобразование и проверку символов
errno.h : отвечает за проверку ошибок
fenv.h : для доступа к окружению, которое управляет операциями с числами с плавающей точкой
float.h : отвечает за работу с числами с плавающей точкой
inttypes.h : для работы с большими целыми числами
iso646.h : содержит ряд определений, которые расширяют ряд логических операций
limits.h : содержит предельные значения целочисленных типов
locale.h : отвечает за работу с локальной культурой
math.h : для работы с математическими выражениями
setjmp.h : определяет возможности нелокальных переходов
signal.h : для обработки исключительных ситуаций
stdalign.h : для выравнивания типов
stdarg.h : обеспечивает поддержку переменного числа параметров
stdatomic.h : для выполнения атомарных операций по разделяемым данным между потоками
stdbool.h : для работы с типом _Bool
stddef.h : содержит ряд вспомогательных определений
stdint.h : для работы с целыми числами
stdio.h : для работы со средствами ввода-вывода
stdlib.h : содержит определения и прототипы функций общего пользования
stdnoreturn.h : содержит макрос noreturn
string.h : для работы со строками
tgmath.h : подключает math.h и complex.h плюс добавляет дополнительные возможности по работе с математическими вычислениями
threads.h : для работы с потоками
time.h : для работы с датами и временем
uchar.h : для работы с символами в кодировке Unicode
wchar.h : для работы с символами
wctype.h : содержит дополнительные возможности для работы с символами
Однако стоит отметить, что в различных средах к этому набору могут добавляться дополнительные встроенные заголовочные файлы для тех или иных целей, например, для работы с графикой.
Определение заголовочных файлов
Кроме стандартных заголовочных файлов мы можем подключать и свои файлы. Например, в той же папке, где находиться главный файл программы, определим еще один файл, который назовем numbers.c .
Определим в нем следующий код:
Здесь просто определена одна переменная. Теперь подключим этот файл в главный файл программы, который, допустим, называется app.c :
При подключении своих файлов их имя указывается в кавычках. И несмотря на то, что в программе не определена переменная number, она будет браться из подключенного файла numbers.c . Но опять же отмечу, важно, что в данном случае файл numbers.c располагается в одной папке с главным файлов программы.
Определение заголовочных файлов
В то же время данный способ прекрасно работает в GCC. Но для разных сред программирования способ подключения файлов может отличаться. Например, в Visual Studio мы получим ошибку. И более правильный подход будет состоять в том, что определить объявление объекта (переменной/константы) или функции в дополнительном заголовочном файле, а определение объекта или функции поместить в стандартный файл с расширением .c .
Например, в нашем в файле numbers.c уже есть определение переменной number. Теперь в ту же папку добавим новый файл numbers.h — файл с тем же названием, но другим расширением.

И определим в numbers.h следующий код:
Ключевое слово extern указывает, что данный объект является внешним. И в этом случае мы могли бы его подключить в файл исходного кода:
Далее чтобы скомпилировать эту программу, передадим компилятору GCC оба файла с исходным кодом — app.c и numbers.c :
Компилятору передаются файлы через пробел и компилируются в один исполняемый файл.
Примечание для Visual Studio
Если разработка ведется в Visual Studio , то не надо подключать файл с исходным кодом ( numbers.c ), однако чтобы Visual Studio видела функционал файла в процессе разработки, может потребоваться подключить заголовочный файл ( numbers.h ). При этом заголовочный файл numbers.h помещается в папку Headers Files .
Как добавить файлы в C++ проект Visual Studio?
В этом посте опишу как добавить новые заголовочные файлы и файлы кода в существующий C++ проект в IDE Microsoft Visual Studio. Не полноценную библиотеку, а только лишь дополнительные файлы кода.
Линковщиком линкуются только добавленные в проект файлы, т.е. те файлы, на которые ему явно указали. Не достаточно просто положить новые файлы кода в корень папки проекта вместе с остальными файлами этого проекта, т.к. это ничего не даст. Новые файлы надо явно добавить в проект, а класть эти файлы именно в директорию или субдиректории проекта вовсе и ненужно, хоть так чаще всего и делают.
Файлы кода
Чтобы добавить .cpp файлы следуйте: Главное меню > Проект > Добавить существующий элемент. Выбрать .cpp файлы для добавления и нажать на кнопку «Добавить». Можно выбирать сразу множество файлов. Файлы можно выбирать, и тем самым добавлять в проект, из любой директории, а не только из директории/папки проекта и субдиректорий. При выборе одних и тех же файлов, т.е. при повторном выборе файлов, они заново добавляться в проект не будут.
Вместо Главного меню можно кликнуть правой кнопкой мыши на проекте и из контекстного меню также выбрать пункты Добавить > Существующий элемент.
Добавленные в проект файлы отразятся в списке файлов проекта в «Обозревателе решений».
Заголовочные файлы
Заголовочные файлы (.h, .hpp) добавлять также как и файлы кода, что добавляли ранее. Помимо этого каталог с заголовочными файлами можно указать здесь: Главное меню > Проект > Свойства проекта > Свойства конфигурации > C/C++ > Общие > Дополнительные каталоги включаемых файлов. Однако, заголовочные файлы можно вообще не добавлять в проект, как добавлялись файлы кода, достаточно просто их подключить с помощью директивы препроцессора #include . Только в этом случае, т.е. если не указать директорию заголовочных файлов (дополнительные каталоги включаемых файлов), в директиве препроцессора #include придётся обязательно писать полный путь к каждому подключаемому файлу. Хотя, я рекомендую всегда писать полные пути к каждому подключаемому заголовочному файлу, для гарантии и большей переносимости кода.
Создание статической библиотеки (VS)
В этой инструкции описан процесс создания и подключения собственных библиотек в Visual Studio 2019/2017.
Сборка библиотеки
- Создайте проект Visual Studio с типом Статическая библиотека (находится в разделе Visual C++ — Классические приложения).
- Добавьте в ваш проект заголовочные файлы и файлы с реализацией классов и функций, которые нужно собрать в библиотеку. Например, создадим файлы TestClass.h и TestClass.cpp:
- Соберите проект: щелкните правой кнопкой мыши по названию проекта в обозревателе решений и выберите Собрать.
- Найдите папку с собранной библиотекой. Она находится по адресу
- [по умолчанию] <путь-к-папке-с-решением>/Debug , если вы выбрали платформу сборки x86 (Win32) и конфигурацию Debug
- <путь-к-папке-с-решением>/Release , если вы выбрали платформу сборки x86 (Win32) и конфигурацию Release
- <путь-к-папке-с-решением>/x64/Debug , если вы выбрали платформу сборки x64 и конфигурацию Debug
- <путь-к-папке-с-решением>/x64/Release , если вы выбрали платформу сборки x64 и конфигурацию Release
- <путь-к-папке-с-решением>/<название платформы>/<название конфигурации> , если у вас настроена нестандартная конфигурация сборки
- В этой папке должен находиться файл .lib с именем вашего проекта (например, если проект называется MyLib, то файл библиотеки назвается MyLib.lib).
Подключение библиотеки в проект
- Добавьте в файлы проекта собранную библиотеку lib.
- Подключите заголовочные файлы библиотеки в коде вашего проекта (или скопируйте их и добавьте в файлы проекта). Если проект с библиотекой и проект с использующим ее приложением находятся в одном решении, то заголовки библиотеки находятся в каталоге уровнем выше: ../<название-проекта> . Например:
Другой вариант: вы можете перейти в настройки проекта, раздел Каталоги VC++, и добавить в дополнительные каталоги подключаемых файлов в начало путь к папке с проектом библиотеки (не забудьте поставить точку с запятой в конце), например: C:/Projects/MySolution/MyLib; (если проект с библиотекой и проект с использующим ее приложением находятся в одном решении, то заголовки библиотеки находятся в каталоге уровнем выше: ../MyLib; ). После этого вы сможете подключать заголовочные файлы без указания пути к каталогам:
Не забудьте, что после внесения изменений в код файлов библиотеки ее необходимо собирать заново, чтобы она исправно функционировала в использующих ее приложениях. Для этого в обозревателе решений щелкните правой кнопкой мыши по названию проекта с библиотекой и выберите Пересобрать.
Как в Си добавлять в программу файлы с расширением h или cpp?
В Visual Studio чтоб добавить в программу файл с расширением h надо правой кнопкой кликнуть в «Обозревателе решений» по папке «Заголовочные файлы», в раскрывшемся меню выбираем » Добавить — > Создать элемент…» В открывшемся окне выбираем «Заголовочный файл (.h)», в нижней части этого окна вводим имя нашего нового файла и жмём кнопку «Добавить».
Если нужно добавить существующий файл h, то всё почти то же самое, только вместо » Добавить — > Создать элемент…» выбирайте » Добавить — > Существующий элемент…», а далее из раскывшегося окна Проводника выбираем нужный файл.
В Visual Studio чтоб добавить в программу файл с расширением cpp делаем всё как и для файлов с расширением h, только вместо «Заголовочный файл (.h)» выбираем «Файл C++ (.cpp).