Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Функции в C: объявление, определение, вызов, аргументы (по значению и по ссылке), рекурсия

Что такое функция?

Функция — именованный блок кода, выполняющий определённую задачу. Позволяет декомпозировать программу, избегать дублирования, улучшать читаемость и тестируемость.

Каждая C-программа начинается с функции main().

Синтаксис: объявление vs определение

// Объявление (прототип) — обычно в .h файле
тип_возврата имя_функции(список_параметров);

// Определение — реализация (в .c файле)
тип_возврата имя_функции(список_параметров) {
    // тело функции
    return значение; // если тип не void
}

Компоненты функции

Пример: функция максимума

// Объявление
int max(int a, int b);

// Определение
int max(int a, int b) {
    return (a > b) ? a : b;
}

// Использование
int main() {
    int m = max(10, 20); // m = 20
    return 0;
}

Вызов функции

При вызове передаются аргументы (actual parameters) — значения, которые копируются в формальные параметры.

int result = max(x, y); // x, y — аргументы

Порядок вычисления аргументов не определён стандартом (компилятор может вычислять в любом порядке). Не пишите код, зависящий от порядка: func(i++, i++) — UB.

Передача аргументов: по значению vs по ссылке

По значению (Call by Value) — стандарт в C

Создаётся копия аргумента. Изменения параметра внутри функции не влияют на аргумент.

void modify(int x) {
    x = 20; // меняет локальную копию
}
int main() {
    int a = 10;
    modify(a);
    printf("%d\n", a); // 10 — не изменилось!
}

По ссылке (Call by Reference) — через указатели

Передаётся адрес переменной. Функция может изменить оригинал.

void modify(int *ptr) {
    *ptr = 20; // разыменование: меняем значение по адресу
}
int main() {
    int a = 10;
    modify(&a); // передаём адрес
    printf("%d\n", a); // 20 — изменилось!
}

Идиома: для изменения аргумента передавайте указатель. Для больших структур — передавайте указатель на const (чтение) или не-const (запись).

Возврат значения

Рекурсия

Функция вызывает сама себя. Нужен базовый случай (остановка) и рекурсивный шаг (упрощение задачи).

// Факториал
unsigned long long factorial(unsigned n) {
    if (n <= 1) return 1;        // базовый случай
    return n * factorial(n - 1); // рекурсивный шаг
}

// Фибоначчи (неэффективно без мемоизации)
unsigned fib(unsigned n) {
    if (n <= 1) return n;
    return fib(n-1) + fib(n-2);
}

Осторожно: глубокая рекурсия → переполнение стека (stack overflow). Для линейных алгоритмов лучше итерация.

Область видимости и время жизни в функциях

Указатели на функции

Функция имеет адрес в памяти. Можно хранить в переменной, передавать как аргумент, возвращать.

// Тип: указатель на функцию, принимающую два int, возвращающую int
int (*operation)(int, int);

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

operation = add;
printf("%d\n", operation(5, 3)); // 8

operation = sub;
printf("%d\n", operation(5, 3)); // 2

// Колбэк (callback) — передача функции как аргумента
void process(int a, int b, int (*op)(int, int)) {
    printf("Result: %d\n", op(a, b));
}
process(10, 5, add); // 15

Функции с переменным числом аргументов (variadic)

Используют <stdarg.h>: va_list, va_start, va_arg, va_end.

#include <stdarg.h>
#include <stdio.h>

double average(int count, ...) {
    va_list args;
    va_start(args, count);
    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += va_arg(args, double);
    }
    va_end(args);
    return sum / count;
}
// average(3, 1.0, 2.0, 3.0) → 2.0

Inline-функции (C99)

inline int square(int x) { return x * x; }

Подсказка компилятору подставить код вместо вызова. Не гарантируется. Для принуждения: static inline в заголовочнике.

Лучшие практики

Язык C

  1. Четыре проверенных паттерна пользовательских функций в C
  2. Как передавать одномерные и двумерные массивы в функции в C — практическое руководство
  3. Стандартные библиотечные функции в C: практическое руководство
  4. Освоение лямбда-функций Python: практические примеры и лучшие практики
  5. Мастерство функций в Verilog для эффективного RTL дизайна
  6. Битовые поля в C: компактное хранение флагов и малых целых чисел
  7. Освоение ввода-вывода файлов в C: создание, открытие и управление файлами
  8. Функции с переменным числом аргументов в C: практическое руководство
  9. Полиморфизм в C++: практическое руководство
  10. Функции в MATLAB: определение, рабочая область, входные и выходные аргументы