Шаг 3 - Компиляция нескольких файлов

Обычно простые программы состоят из одного исходного файла. Дело обстоит несколько сложнее, если эта программа становится большой. При работе с такой программой может возникнуть несколько достаточно серьезных проблем:

Это далеко не все пробемы, которые могут возникнуть при наличии программы "монстра". Поэтому при разработке программ рекомендуется их разбивать на куски, которые функционально ограничены и закончены. В этом значительно помогает сам язык C++, предоставляя свой богатый синтаксис.

Для того, чтобы вынести функцию или переменную в отдельный файл надо перед ней поставить зарезервированное слово extern. Давайте для примера создадим программу из нескольких файлов. Сначала создадим главную программу, в которой будут две внешние процедуры. Назовем этот файл main.c:

#include <stdio.h>

// описываем функцию f1() как внешнюю
extern int f1();

// описываем функцию f2() как внешнюю
extern int f2();

int main()
{
	int n1, n2;

	n1 = f1();
	n2 = f2();

	printf("f1() = %d\n",n1);
	printf("f2() = %d\n",n2);

	return 0;
}

Теперь создаем два файла, каждый из которых будет содержать полное определение внешней функции из главной программы. Файлы назовем f1.c и f2.c:

// файл f1.c
int f1()
{
	return 2;
}

// файл f2.c
int f2()
{
	return 10;
}

После этого процесс компиляции программы с помощью gcc будет выглядеть несколько иначе от описанного в "Шаг 1 - Компиляция программ на языке C/C++".

Компилировать можно все файлы одновременно одной командой, перечисляя составные файлы через пробел после ключа -c:

gcc -c main.c f1.c f2.c

Или каждый файл в отдельности:

gcc -c f1.c
gcc -c f2.c
gcc -c main.c

В результате работы компилятора мы получим три отдельных объектных файла:

main.o
f1.o
f2.o

Чтобы их собрать в один файл с помощью gcc надо использовать ключ -o, при этом линкер соберет все файлы в один:

gcc main.o f1.o f2.o -o rezult

В результате вызова полученной программы rezult командой:

./rezult

На экране появится результат работы:

dron:~# ./rezult
f1() = 2
f2() = 10
dron:~#

Теперь, если мы изменим какую-то из процедур, например f1():

int f1()
{
	return 25;
}

То компилировать заново все файлы не придется, а понадобится лишь скомпилировать измененный файл и собрать результирующий файл из кусков:

dron:~# gcc -c f1.c
dron:~# gcc main.o f1.o f2.o -o rezult2
dron:~# ./rezult2
f1() = 25
f2() = 10
dron:~#

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


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Кузин Андрей.