Интернет-магазин
- Программное обеспечение
- Дистрибутивы
- 1С: Предприятие
- Офисное ПО
- СПО для Windows
- Игры для Linux
- Виртуализация VMware
- vCenter Converter
- VMware vSphere
- vSphere Hypervisor
- Сертифицированно ФСТЭК
- ССПТ-2
- SUSE
- Altel
- АПКШ «Континент»
- ПАК "Соболь"
- Аппаратное обеспечение
- Открытое аппаратное обеспечение
- Серверы
- Системы видеонаблюдения
- 3D Печать
- Литература и обучение
- Журналы, подписка
- Книги
- Учебные курсы
- Услуги
- Лицензии и купоны на тех.поддержку
- Консалтинг, сервис, техническая поддержка
- Реклама
- Атрибутика
- Новинки
- Распродажа
- Все товары сразу
Продукты Oracle
Где купить ?
Дистрибутивы
Помощь



Пример проекта из нескольких файлов
Пример проекта из нескольких файлов
Напишем теперь программу, состоящую из двух исходных файлов и одного заголовочного. Для этого возьмём наш калькулятор и переделаем его. Теперь после введения первого числа надо сразу вводить действие. Если действие оперирует только с одним числом (как в случае синуса, косинуса, тангенса, квадратного корня), результат сразу будет выведен. Если понадобится второе число, оно будет специально запрашиваться.
Создадим каталог проекта kalkul2. В нём создадим три файла: calculate.h, calculate.c, main.c.
Файл calculate.h:
///////////////////////////////////////
// calculate.h
#ifndef CALCULATE_H_
#define CALCULATE_H_
float Calculate(float Numeral, char Operation[4]);
#endif /*CALCULATE_H_*/
Файл calculate.c:
////////////////////////////////////
// calculate.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "calculate.h"
float Calculate(float Numeral, char Operation[4])
{
float SecondNumeral;
if(strncmp(Operation, "+", 1) == 0)
{
printf("Второе слагаемое: ");
scanf("%f",&SecondNumeral);
return(Numeral + SecondNumeral);
}
else if(strncmp(Operation, "-", 1) == 0)
{
printf("Вычитаемое: ");
scanf("%f",&SecondNumeral);
return(Numeral - SecondNumeral);
}
else if(strncmp(Operation, "*", 1) == 0)
{
printf("Множитель: ");
scanf("%f",&SecondNumeral);
return(Numeral * SecondNumeral);
}
else if(strncmp(Operation, "/", 1) == 0)
{
printf("Делитель: ");
scanf("%f",&SecondNumeral);
if(SecondNumeral == 0)
{
printf("Ошибка: деление на ноль! ");
return(HUGE_VAL);
}
else
return(Numeral / SecondNumeral);
}
else if(strncmp(Operation, "pow", 3) == 0)
{
printf("Степень: ");
scanf("%f",&SecondNumeral);
return(pow(Numeral, SecondNumeral));
}
else if(strncmp(Operation, "sqrt", 4) == 0)
return(sqrt(Numeral));
else if(strncmp(Operation, "sin", 3) == 0)
return(sin(Numeral));
else if(strncmp(Operation, "cos", 3) == 0)
return(cos(Numeral));
else if(strncmp(Operation, "tan", 3) == 0)
return(tan(Numeral));
else
{
printf("Неправильно введено действие ");
return(HUGE_VAL);
}
}
Файл main.c:
////////////////////////////////////////
// main.c
#include <stdio.h>
#include "calculate.h"
int main(void)
{
float Numeral;
char Operation[4];
float Result;
printf("Число: ");
scanf("%f",&Numeral);
printf("Арифметическое действие (+,-,*,/,pow,sqrt,sin,cos,tan): ");
scanf("%s",&Operation);
Result = Calculate(Numeral, Operation);
printf("%6.2f\n",Result);
return 0;
}
У нас есть два файла исходного кода (c-файлы) и один заголовочный (h-файл). Заголовочный включается в оба c-файла.
Скомпилируем calculate.c.
gcc -c calculate.c
Получили calculate.o. Затем main.c.
gcc -c main.c
И вот он main.o перед нами! Теперь, как вам уже, наверное, подсказывает интуиция, надо из этих двух объектных файлов сделать запускаемый.
gcc calculate.o main.o -o kalkul
Упс... и не получилось... Вместо столь желаемого запускаемого файла, в консоли появилась какая-то ругань:
calculate.o(.text+0x1b5): In function `Calculate':
calculate.c: undefined reference to `pow'
calculate.o(.text+0x21e):calculate.c: undefined reference to `sqrt'
calculate.o(.text+0x274):calculate.c: undefined reference to `sin'
calculate.o(.text+0x2c4):calculate.c: undefined reference to `cos'
calculate.o(.text+0x311):calculate.c: undefined reference to `tan'
collect2: ld returned 1 exit status
Давайте разберёмся, за что нас так отругали. Undefined reference означает ссылку на функцию, которая не определена. В данном случае gcc не нашёл определения функций pow, sqrt, sin, cos, tan. Где же их найти?
Как уже говорилось раньше, определения функций могут находиться в библиотеках. Это скомпилированные двоичные файлы, содержащие коллекции однотипных операций, которые часто вызываются из многих программ, а потому нет смысла многократно писать их код в программах. Стандартное расположение файлов библиотек – каталоги /usr/lib и /usr/local/lib (при желании можно добавить путь). Если библиотечный файл имеет расширение .a, то это статическая библиотека, то есть при компоновке весь её двоичный код включается в исполняемый файл. Если расширение .so, то это динамическая библиотека. Это значит в исполняемый файл программы помещается только ссылка на библиотечный файл, а уже из него и запускается функция.
Когда мы писали программу hello, мы использовали функцию printf для вывода текстовой строки. Однако, как вы помните, мы нигде не писали определения этой функции. Откуда же она тогда вызывается?
Просто при компоновке любой программы компилятор gcc по умолчанию включает в запускаемый файл библиотеку libc. Это стандартная библиотека языка C. Она содержит рутинные функции, необходимые абсолютно во всех программах, написанных на C, в том числе и функцию printf. Поскольку библиотека libc нужна во всех программах, она включается по умолчанию, без необходимости давать отдельное указание на её включение.
Остальные библиотеки надо требовать включать явно. Ведь нельзя же во все программы помещать абсолютно все библиотеки. Тогда исполняемый файл раздуется до немыслимо крупных размеров. Одним программам нужны одни функции, другим – другие. Зачем же засорять их ненужным кодом! Пусть остаётся только то, что реально необходимо.
Нам в данном случае нужна библиотека libm. Именно она содержит все основные математические функции. Она требует включения в текст программы заголовочного файла <math.h>.
Помимо этого дистрибутивы Linux содержат и другие библиотеки, например:
libGL Вывод трёхмерной графики в стандарте OpenGL. Требуется заголовочный файл <GL/gl.h>.
libcrypt Криптографические функции. Требуется заголовочный файл <crypt.h>.
libcurses Псевдографика в символьном режиме. Требуется заголовочный файл <curses.h>.
libform Создание экранных форм в текстовом режиме. Требуется заголовочный файл <form.h>.
libgthread Поддержка многопоточного режима. Требуется заголовочный файл <glib.h>.
libgtk Графическая библиотека в режиме X Window. Требуется заголовочный файл <gtk/gtk.h>.
libhistory Работы с журналами. Требуется заголовочный файл <readline/readline.h>.
libjpeg Работа с изображениям в формате JPEG. Требуется заголовочный файл <jpeglib.h>.
libncurses Работа с псевдографикой в символьном режиме. Требуется заголовочный файл <ncurses.h>.
libpng Работа с графикой в формате PNG. Требуется заголовочный файл <png.h>.
libpthread Многопоточная библиотека POSIX. Стандартная многопоточная библиотека для Linux. Требуется заголовочный файл <pthread.h>.
libreadline Работа с командной строкой. Требуется заголовочный файл <readline/readline.h>.
libtiff Работа с графикой в формате TIFF. Требуется заголовочный файл <tiffio.h>.
libvga Низкоуровневая работа с VGA и SVGA. Требуется заголовочный файл <vga.h>.
А также многие-многие другие.
Обратите внимание, что названия всех этих библиотек начинаются с буквосочетания lib-. Для их явного включения в исполняемый файл, нужно добавить к команде gcc опцию -l, к которой слитно прибавить название библиотеки без lib-. Например, чтобы включить библиотеку libvga надо указать опцию -lvga.
Нам нужны математические функции pow, sqrt, sin, cos, tan. Они, как уже было сказано, находятся в математической библиотеке libm. Следовательно, чтобы подключить эту библиотеку, мы должны указать опцию -lm.
gcc calculate.o main.o -o kalkul -lm
Ура! Наконец-то наш запускаемый файл создан!
Оглавление | Назад | Вперед
[ опубликовано 06/09/2006 ]
Дмитрий Пантелеичев (dimanix2006 at rambler dot ru) - Пример проекта из нескольких файлов Версия для печатиБиблиотека Линуксцентра. Список разделов
- Презентации
- Книги и руководства
- Linux для пользователя
- Разработка программного обеспечения для Linux. Инструментарий
- Программирование на Shell (Unix)
- Учебник FTP
- Энциклопедия VMWare
- Slackware Linux Essentials
- Slackware ЧаВО
- Разработка графического интерфейса с помощью библиотеки Qt3
- Разделы диска и средства для работы с ними в Линукс
- Введение в POSIX'ивизм
- Статьи
- Пресс-релизы ЛинуксЦентра
- История Linux
- Linux'оиды шутят
Топ-10 интернет магазина Линуксцентра
- Лицензия на право установки и использования операционной системы специального назначения "Astra Linux Special Edition" РУСБ.10015-07 (формат BOX), сертифицированной ФСБ
- Linux Format #2 Электронная версия журнала, февраль 2018
- Linux Format #1 Электронная версия журнала, январь 2018
- LibreOffice 5.3 (1DVD) (Поставляется с лицензионным договором присоединения)
- Журнал Linux Format #12 + DVD, декабрь 2017
- Linux Format #12 Электронная версия журнала, декабрь 2017
- Журнал Linux Format #11 + DVD, ноябрь 2017
- Журнал Linux Format #10 + DVD, октябрь 2017
- Журнал Linux Format #9 + DVD, сентябрь 2017
- Linux Format #11 Электронная версия журнала, ноябрь 2017
© 2000-2018 ГНУ/Линуксцентр © Группа компаний
info@linuxcenter.ru - По вопросам заказов, оплаты, доставки, общим вопросам
zabota@linuxcenter.ru - По проблемам работы интернет-магазина, функционирования сайта
partner@linuxcenter.ru - По вопросам сотрудничества, партнерства, оптовых закупок
Перепечатка, цитирование и переработка материалов Linuxcenter.Ru разрешается в любой форме, при этом обязательна ссылка на www.linuxcenter.ru
Свидетельство о регистрации СМИ ЭЛ № ФС 77 - 37801 выдано Федеральной службой по надзору в сфере связи,
информационных технологий и массовых коммуникаций
15.10.2009
12+
Страница загружена за 0.08 сек.