Ответ 1
Это процесс:
source header source header header
\ / \ | / /
\ / \ | / /
PREPROCESSOR PREPROCESSOR
| |
V V
preprocessed code preprocessed code
| |
COMPILER COMPILER
| |
V V
object code object code
\ /
\ /
\ /
LINKER
|
V
executable
Препроцессирование
#include
для этого первого шага. Он инструктирует препроцессор обрабатывать указанный файл и вставляет результат в выходной файл.
Если A
включает B
и C
, а B
включает C
, вывод препроцессора для A
будет включать обработанный текст C
дважды.
Это проблема, так как это приведет к дублированию деклараций. Исправление состоит в том, чтобы использовать препроцессорные переменные, отслеживать, включен ли исходный код (aka head guard).
#ifndef EXAMPLE_H
#define EXAMPLE_H
// header contents
#endif
В первый раз EXAMPLE_H
равен undefined, а препроцессор будет оценивать содержимое в блоке ifndef
/endif
. Во второй раз он пропустит этот блок. Таким образом, обработанный вывод изменяется, и определения включаются только один раз.
Это настолько распространено, что существует нестандартная директива, реализованная некоторыми компиляторами, которая короче и не требует выбора уникальной переменной препроцессора:
#pragma once
// header contents
Вы можете понять, насколько переносимым вы хотите свой код на C/С++ и какой защитник заголовка использовать.
Защитники заголовков гарантируют, что содержимое каждого файла заголовка будет присутствовать не более одного раза в предварительно обработанном коде для единицы перевода.
Компиляция
Компилятор генерирует машинный код из вашего предварительно обработанного C/С++.
Как правило, файлы заголовков включают только объявления, а не фактические определения (аналогичные реализации). Компилятор содержит таблицу символов для всего, что в настоящее время отсутствует в определении.
Связь
Компонент объединяет объектные файлы. Он соответствует определениям (аналогичным реализациям) со ссылками на таблицу символов.
Возможно, два объектных файла предоставляют определение, а компоновщик - один. Это происходит, если вы поместили исполняемый код в свои заголовки. Это обычно не происходит в C, но это происходит очень часто в С++ из-за шаблонов.
Заголовок "код", будь то декларации или определения, включается несколько раз во все объектные файлы, но компоновщик объединяет все это вместе, так что он присутствует только один раз в исполняемом файле. ( Я исключаю встроенные функции, которые присутствуют несколько раз.)