Глава 6: Функции — Строим Модульный Код ======================================= Функции в языке C — это фундаментальный механизм для **организации, структурирования и повторного использования кода**. Они позволяют разбивать большие и сложные программы на маленькие, управляемые и логически связанные блоки. Думайте о функциях как о "строительных блоках", каждый из которых выполняет свою специфическую задачу. Преимущества использования функций: * **Модульность**: Программа становится более модульной и легче для понимания. * **Переиспользование кода**: Один раз написанную функцию можно вызвать многократно в разных частях программы, избегая дублирования. * **Удобство отладки**: Локализация ошибок становится проще, так как можно тестировать каждую функцию по отдельности. * **Сопровождаемость**: Изменения в одной функции не влияют на другие, если их интерфейсы остаются неизменными. Основные понятия: Объявление и Определение ------------------------------------------- В языке C каждая функция должна быть **объявлена** (прототип функции) и **определена** (реализация функции). * **Объявление функции (Function Declaration / Prototype)**: Сообщает компилятору о *существовании* функции, её имени, типе возвращаемого значения и типах её параметров. Это позволяет компилятору проверить корректность вызовов функции до того, как он увидит её полную реализацию. Обычно объявления размещают в начале файла или в отдельных заголовочных файлах (``.h``). * **Определение функции (Function Definition)**: Содержит фактический *код* (инструкции), который выполняется, когда функция вызывается. Оно включает тело функции, заключенное в фигурные скобки ``{}``. Пример объявления и определения функции: .. code-block:: c // Пример 6.1: Объявление и Определение Функции Sum // Объявление (прототип): Сообщает компилятору, что функция 'sum' существует. // Принимает два целых числа (int) и возвращает целое число (int). int sum(int a, int b); // Определение: Реализация функции 'sum'. // Здесь происходит фактическое сложение двух чисел. int sum(int a, int b) { return a + b; // Возвращаем результат сложения. } // Главная функция программы int main() { // Вызов функции 'sum' с аргументами 3 и 4. // Результат (7) будет присвоен переменной 'result'. int result = sum(3, 4); printf("Сумма: %d\n", result); // Выводим полученную сумму. return 0; // Завершаем программу успешно. } Аргументы и Возвращаемое Значение --------------------------------- Функции могут принимать **аргументы** (также называемые *параметрами* или *входными данными*) и возвращать результат через оператор ``return``. * **Аргументы**: Это значения, которые передаются в функцию для её обработки. Они указываются в круглых скобках после имени функции в объявлении и определении. Каждый аргумент имеет свой тип и имя. * **Возвращаемое значение**: Это результат, который функция передаёт обратно вызвавшему её коду. Тип возвращаемого значения указывается перед именем функции. Если функция не возвращает никакого значения, используется ключевое слово ``void``. .. code-block:: c // Пример 6.2: Функции с void и возвращаемым значением // Функция без аргументов и без возвращаемого значения (void). // Просто выводит приветствие. void print_hello() { printf("Привет из функции print_hello!\n"); } // Функция, принимающая два целых числа и возвращающая их произведение. int multiply(int x, int y) { return x * y; // Возвращаем результат умножения. } // Главная функция программы int main() { print_hello(); // Вызываем функцию, которая просто печатает сообщение. // Вызываем функцию 'multiply' с аргументами 2 и 3. // Результат (6) будет выведен напрямую. printf("Произведение: %d\n", multiply(2, 3)); return 0; // Завершаем программу успешно. } Важные аспекты использования функций: * **Согласованность типов**: Количество, порядок и типы аргументов при вызове функции должны точно совпадать с её объявлением (прототипом) и определением. * **Гибкость расположения**: Вы можете объявить функцию до её использования (например, до ``main()``), а определить её полную реализацию после ``main()`` или в другом файле. Это способствует более чистому и организованному коду. * **Уникальность имен**: Каждая функция в вашей программе должна иметь уникальное имя. * **Область видимости**: Переменные, объявленные внутри функции, являются *локальными* и доступны только внутри этой функции. Практический пример: Использование функций ------------------------------------------ Давайте создадим полноценный файл ``functions_demo.c``, демонстрирующий несколько функций. .. code-block:: c // Пример 6.3: Практический пример использования функций #include // Включаем стандартную библиотеку ввода-вывода для printf // Объявления (прототипы) функций. // Эти строки сообщают компилятору о существовании функций до их определения. void greet(); // Функция без аргументов и без возвращаемого значения int square(int n); // Функция принимает int, возвращает int double calculate_area(double radius); // Функция принимает double, возвращает double // Главная функция - точка входа в программу. int main() { // Вызов функции greet(). greet(); // Вызов функции square() с аргументом 5 и вывод результата. printf("Квадрат 5: %d\n", square(5)); // Вызов функции calculate_area() с аргументом 3.0 и вывод результата. // Обратите внимание на спецификатор формата %lf для double. printf("Площадь круга радиусом 3.0: %.2lf\n", calculate_area(3.0)); return 0; // Успешное завершение программы. } // Определение функции greet(). // Эта функция просто печатает приветственное сообщение. void greet() { printf("Добро пожаловать в мир функций C!\n"); } // Определение функции square(). // Эта функция принимает целое число 'n' и возвращает его квадрат. int square(int n) { return n * n; } // Определение функции calculate_area(). // Эта функция принимает радиус 'radius' (тип double) // и возвращает площадь круга (pi * r^2). // Для простоты используем 3.14159 в качестве PI. double calculate_area(double radius) { const double PI = 3.14159; // Константа для PI return PI * radius * radius; } Компиляция: .. code-block:: bash gcc functions_demo.c -o funcdemo ./funcdemo Результат: .. code-block:: none Добро пожаловать в функции! Квадрат 5: 25 Площадь круга радиусом 3.0: 28.27 .. note:: **Хороший стиль программирования**: * Рекомендуется размещать **объявления функций** в начале файла ``.c`` или, что ещё лучше, в **заголовочных файлах** (файлы с расширением ``.h``). Это обеспечивает единообразие и упрощает управление крупными проектами. * **Разделение на файлы**: В больших проектах часто каждая функция (или группа связанных функций) определяется в отдельном ``.c`` файле, а их объявления помещаются в соответствующий ``.h`` файл. .. code-block:: text * `man gcc` - Руководство по использованию компилятора GCC. * `man printf` - Руководство по функции `printf` в стандартной библиотеке C. * `C Functions (W3Schools) `_ - Дополнительный материал по функциям C (на английском). * `Function Prototypes in C (GeeksforGeeks) `_ - Подробнее о прототипах функций (на английском).