Сборка программ для АСУб и ЭВМб. Тема 3-5

Содержание

Слайд 2

Темы лекции Процесс компиляции и сборки программы Файлы *.cpp и *.h.

Темы лекции

Процесс компиляции и сборки программы
Файлы *.cpp и *.h.
Директивы

препроцессора.
Сборка проекта из нескольких файлов
Макропроцессор на примере М4.
Создание диалекта
Слайд 3

Для объявления глобальной переменной, внешней к данной единице трансляции, либо внутри

Для объявления глобальной переменной, внешней к данной единице трансляции, либо внутри

функции используется ключевое слово extern (чтобы это объявление не было понято компилятором как определение локальной переменной). 
Слайд 4

Разбиение программы на модули (файлы) Самые простые программы могут состоять из

Разбиение программы на модули (файлы)

Самые простые программы могут состоять из одной

функции main
Чуть более сложные включают в себя другие функции
По мере возрастания сложности программы функций становится слишком много, в них становится тяжело ориентироваться
Выход – разбиение функций на отдельные модули по смысловому значению
Слайд 5

Структура модуля Две основные части: интерфейс (заголовок модуля – файл .h); реализация (реализация модуля файл .сpp).

Структура модуля
Две основные части:
интерфейс (заголовок модуля – файл .h);
реализация (реализация модуля

файл .сpp).
Слайд 6

Использование функций

Использование функций

Слайд 7

Заголовок модуля Заголовок модуля – интерфейсная часть, представленная в виде файла

Заголовок модуля

Заголовок модуля – интерфейсная часть, представленная в виде файла с

расширением .h.
Основное содержание:
описание внешних типов данных;
описание внешних переменных и констант;
описание прототипов внешних функций.
Слайд 8

Реализация модуля Реализация модуля – файл с расширением .cpp Основное содержание:

Реализация модуля

Реализация модуля – файл с расширением .cpp
Основное содержание:
описание внутренних типов

данных;
описание внутренних и внешних переменных и констант;
реализация внешних и внутренних функций.
Слайд 9

Подключение модулей Подключение модуля в программу осуществляется двумя действиями: подключение файла

Подключение модулей

Подключение модуля в программу осуществляется двумя действиями:
подключение файла заголовка модуля

с помощью директивы #include;
подключение файла текста программы модуля в проект.
Слайд 10

Частные случаи модулей Модуль содержит только часть реализацию: единственный модуль в

Частные случаи модулей

Модуль содержит только часть реализацию: единственный модуль в программе,

содержащий только функцию main.
Модуль содержит только часть заголовок: в модуле производится описание глобальных типов данных.
Слайд 11

Как организуется модуль на языке C++? Модуль логически состоит из двух

Как организуется модуль на языке C++?

Модуль логически состоит из двух файлов

- файла с исходным кодом (source file) и заголовочного файла (header file)
файл с исходным кодом (module.cpp) включает в себя определения функций, а также определения глобальных переменных и констант (если они есть); в первой строке обычно подключается заголовочный файл того же модуля:
#include "module.h"
заголовочный файл (module.h) включает в себя прототипы функций, определения констант, объявления глобальных переменных - но только для тех элементов модуля, о которых должны знать другие модули
Слайд 12

Как организуется модуль на языке C++? Если какой-либо модуль использует данный,

Как организуется модуль на языке C++?

Если какой-либо модуль использует данный, необходимо

подключить его заголовочный файл (в двойных кавычках – это указывает на то, что заголовочный файл не системный, а собственный):
#include "module.h"
Главный модуль программы обычно содержит только функцию main и не имеет заголовочного файла (поскольку функция main не используется в других модулях)
Некоторые модули включают только заголовочный файл – например, содержащий определения глобальных констант
Слайд 13

Заголовочные файлы

Заголовочные файлы

Слайд 14

Препроцессор Препроцессор – программа, осуществляющая обработку текста программы перед ее непосредственной

Препроцессор

Препроцессор – программа, осуществляющая обработку текста программы перед ее непосредственной компиляцией.

Обработка осуществляется согласно специальным указаниям, называемым директивами препроцессора
Слайд 15

Препроцессор Препроцессор изменяет исходный текст программы: Удаляет комментарии и выполняет директивы

Препроцессор

Препроцессор изменяет исходный текст программы:
Удаляет комментарии и выполняет директивы препроцессора, которыми

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

Директива препроцессора – это инструкция, которая включает в текст программы файл,

Директива препроцессора – это инструкция, которая включает в текст программы файл,

содержащий описание множества функций, что позволяет правильно компилировать программу.
Это важно
все директивы препроцессора начинаются со знака #;
после директивы препроцессора точка с запятой не ставится.
Слайд 17

Директива #include позволяет включать в текст программы указанный файл. Имя файла

Директива #include позволяет включать в текст программы указанный файл.
Имя файла

может быть указано двумя способами:
#include
#include "my_file.h”
Если файл является стандартной библиотекой и находится в папке компилятора, он заключается в угловые скобки <>.
Если файл находится в текущем каталоге проекта, он указывается в кавычках "".

Синтаксис подключения заголовочных файлов:

Слайд 18

Макросы Макросом или макроопределением называется идентификатор, связанный директивой #define с лексемой

Макросы

Макросом или макроопределением называется идентификатор, связанный директивой #define с лексемой или

последовательностью лексем
#define МАКРОС ЗНАЧЕНИЕ
#define M_E 2.71828182845904523536 #define M_PI 3.14159265358979323846
Слайд 19

Слайд 20

Заголовочные файлы

Заголовочные файлы

Слайд 21

Директивы условной компиляции

Директивы условной компиляции

Слайд 22

Директивы условной компиляции Примеры: #define A 5 #if A>10 puts(“Message 1”);

Директивы условной компиляции

Примеры:
#define A 5
#if A>10
puts(“Message 1”);
#else
puts(“Message 2”);
#endif
#define A

2
#if A==1
puts("A=1!");
#elif A==2
puts("A=2!");
#else
puts("uncknown A!");
#endif
Слайд 23

Директивы условной компиляции #ifndef идентификатор … #endif #ifdef идентификатор … #endif

Директивы условной компиляции

#ifndef идентификатор

#endif

#ifdef идентификатор

#endif

Слайд 24

Директивы условной компиляции Примеры: #define DEBUG_MODE … #ifdef DEBUG_MODE puts(“Режим отладки”);

Директивы условной компиляции

Примеры:
#define DEBUG_MODE

#ifdef DEBUG_MODE
puts(“Режим отладки”);
#endif

#define TEST_MODE
int main(int argc,

char *argv[])
{
#ifdef TEST_MODE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int val;
scanf("%d",&val);
printf("%d",val);
return 0;
}
Слайд 25

Как происходит сборка программы? Сборка (build) состоит из 3 основных этапов:

Как происходит сборка программы?

Сборка (build) состоит из 3 основных этапов:
на этапе

препроцессинга (preprocessing) директивы препроцессора (например, #include) заменяются содержимым указанного в них заголовочного файла, в результате файл с исходным кодом дополняется прототипами указанных там функций и объявлениями глобальных переменных – за счет этого в файле можно вызывать указанные функции (прототип впереди) и использовать глобальные переменные (объявление впереди). Препроцессор может создавать на диске временные файлы, которые, однако, удаляются после окончания сборки
Слайд 26

Как происходит сборка программы? Сборка (build) состоит из 3 основных этапов:

Как происходит сборка программы?

Сборка (build) состоит из 3 основных этапов:
на этапе

компиляции (compiling) для каждого исходного файла составляются таблицы определенных в нем функций и глобальных переменных, все определенные функции переводятся на машинный язык (при переводе на машинный язык могут выявляться ошибки компиляции). Результатом работы компилятора являются файлы module.obj (объектные файлы) для каждого использованного в программе модуля
Слайд 27

Как происходит сборка программы? Сборка (build) состоит из 3 основных этапов:

Как происходит сборка программы?

Сборка (build) состоит из 3 основных этапов:
на этапе

связывания (linking) происходит привязка всех используемых (вызванных) функций и глобальных переменных к той таблице, в которой они определены;
если определения не обнаружены ни в одной таблице, происходит ошибка связывания (unresolved external symbol …).
Результатом связывания является файл program.exe – исполняемый файл
Слайд 28

Что при сборке происходит с библиотечными функциями? Прототипы функций находятся в

Что при сборке происходит с библиотечными функциями?

Прототипы функций находятся в заголовочных

файлах (iostream, math.h, stdio.h, string.h и т.п.)
Объектные файлы с уже переведенными на машинный язык определениями функций заранее собраны в библиотеки (файлы с расширением lib или dll)
определения из статических библиотек (расширение lib) на этапе связывания добавляются в исполняемый файл программы
определения из динамических библиотек (расширение dll) в исполняемый файл не добавляются; вместо этого в ссылке на соответствующую функцию указывается, что она находится в динамической библиотеке, и при ее вызове происходит обращение к библиотеке
поэтому, статические библиотеки нужны только на этапе связывания, а динамические – и на этапе исполнения программы
Слайд 29

Использование условной компиляции При многократном подключении модуля необходимо организовать однократность его

Использование условной компиляции

При многократном подключении модуля необходимо организовать однократность его компиляции.

Это осуществляется с использованием директив условной компиляции в файле заголовка модуля в формате:
#ifndef имя_модуля
#define имя_модуля
… текст заголовка модуля …
#endif
ИЛИ
#pragma once
Слайд 30

Что такое #ifndef-#define- #endif? Это, как и #include, директивы препроцессора Директива

Что такое #ifndef-#define- #endif?

Это, как и #include, директивы препроцессора
Директива #define позволяет определить

переменную препроцессора (например, ADD_H)
Директива #ifndef позволяет выяснить, определена ли переменная препроцессора. Если она не определена, участок кода до директивы
#endif вставляется в программу, если же
определена – выбрасывается из нее
Нужны эти скобки для того, чтобы текст заголовочного файла не мог вставиться в исходный файл дважды
Слайд 31

Заголовочные файлы

Заголовочные файлы

Слайд 32

Заголовочные файлы

Заголовочные файлы