компиляция программ, состоящих из двух и более файлов исходного кода
Простейший подход к использованию нескольких функций предусматривает их помещение в один файл. Затем нужно просто скомпилировать этот файл, как если бы он содержал единственную функцию. Другие подходы в большей степени зависят от системы, как показано в последующих разделах.
Unix
В этом случае предполагается, что в системе Unix имеется компилятор Unix С — сс. (Первоначальный компилятор сс был выведен из употребления, но во многих системах Unix команда сс служит псевдонимом команды запуска какого-то другого компилятора, обычно gcc или clang.) Пусть file1.с и file2.с — два файла, содержащие функции С. Тогда следующая команда скомпилирует оба файла и создаст исполняемый файл по имени а.out:
сс file1.с file2.с
Кроме того, создаются два объектных файла — filel.о и file2.о. Если позже вы измените содержимое file1.с, но не filе2.с, можно скомпилировать первый файл и объединить его с объектным кодом из второго файла с помощью такой команды:
сс file1.с file2.о
В Unix имеется команда make, которая автоматизирует управление многофайловыми программами, но эта тема выходит за рамки настоящей книги. Обратите внимание, что утилита Terminal в системе OS X открывает среду командной строки Unix, но компиляторы командной строки (GCC и Clang) придется загрузить из веб-сайта Apple.
Linux
В этом случае предполагается, что в системе Linux установлен компилятор GNU С — GCC. Пусть file1.с и filе2.с — два файла, содержащие функции С. Тогда следующая команда скомпилирует оба файла и создаст исполняемый файл по имени а. out:
gcc file1.с file2.c
В дополнение создаются два объектных файла filel.о и filе2.о. Если позже вы измените содержимое файла file1.с, но не file2.с, можно скомпилировать первый файл и объединить его с объектным кодом из второго файла, посредством такой команды:
gcc file1.с file2.o
350 глава 9
Компиляторы командной строки DOS
Большинство компиляторов командной строки DOS работают аналогично команде сс в Unix, но применяют другое имя. Отличие в том, что объектные файлы получают расширение .obj, а не .о. Некоторые компиляторы вместо файлов с объектным кодом генерируют промежуточные файлы с кодом на языке ассемблера или другим специальным кодом.
Компиляторы интегрированных сред разработки в Windows и Apple
Компиляторы интегрированных сред разработки (integrated development environment — IDE) для операционных систем Windows и Macintosh являются ориентированными на проекты. Проект описывает ресурсы, используемые конкретной программой. Эти ресурсы включают и файлы исходного кода. Если вы применяли один из этих компиляторов, то вероятно должны были создавать проекты для выполнения однофайловых программ. В случае многофайловых программ найдите команду меню, которая позволяет добавлять в проект файл исходного кода. Вы должны обеспечить присутствие в проекте всех файлов исходного кода (с расширением .с). Во многих IDE-средах наличие в списке проекта заголовочных файлов (с расширением.h) не обязательно. Идея в том, что проект управляет использованием файлов исходного кода, а с помощью директив #include в этих файлах указываются применяемые заголовочные файлы. Тем не менее, в случае XCode заголовочные файлы должны быть добавлены в проект.
Использование заголовочных файлов
Если поместить функцию main() в один файл, а определения собственных функций — в другой, то в первом файле по-прежнему будут нужны прототипы функций. Вместо того чтобы набирать их каждый раз, когда применяется файл с функциями, прототипы функций можно сохранить в заголовочном файле. Именно это сделано в стандартной библиотеке С путем помещения, к примеру, прототипов функций ввода- вывода в файл stdio.h, а прототипов математических функций — в файл math.h Со своими файлами функций вы можете поступить аналогично.
Вы также часто будете пользоваться препроцессором С для определения констант, применяемых в программе. Такие определения возможны только для файла, содержащего директивы #define. Если разнести функции, применяемые в программе, но отдельным файлам, то также придется обеспечить доступность каждому файлу директив #def ine. Наиболее прямолинейный способ предусматривает повторный набор директив в каждом файле, но это требует времени и увеличивает вероятность допущения ошибки при наборе. Вдобавок возникает проблема сопровождения: если вы решите изменить значение в директиве #define, то нужно будет не забыть сделать это в каждом файле. Более разумное решение предполагает размещение директив #define в заголовочном файле с последующим использованием директивы #include в каждом файле исходного кода.
Читать дальше