0Pricing
C Academy · Урок

Таблицы указателей на функции

Шаблоны диспетчеризации

«Таблицы указателей на функции» — бесплатный урок C Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.

Таблицы функций

Указатели на функции можно хранить в массиве и создать таблицу диспетчеризации. Индекс или код выбирает функцию для запуска, заменяя длинные цепочки if-else или switch.

#include <stdio.h>

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

int main(void) {
    int (*ops[2])(int,int) = { add, sub };
    printf("%d\n", ops[0](5, 3));
    printf("%d\n", ops[1](5, 3));
    return 0;
}

Индексация таблицы

Выбирайте операцию во время выполнения, обращаясь к элементу массива по индексу. Индекс может поступать от пользователя или из состояния программы.

#include <stdio.h>

int mul(int a, int b) { return a * b; }
int add(int a, int b) { return a + b; }

int main(void) {
    int (*ops[2])(int,int) = { add, mul };
    int choice = 1;
    printf("%d\n", ops[choice](6, 7));
    return 0;
}

Замена switch

Таблица диспетчеризации часто понятнее, чем switch, если каждый вариант всего лишь вызывает функцию.

#include <stdio.h>

void start(void) { printf("start\n"); }
void stop(void)  { printf("stop\n"); }
void pause(void) { printf("pause\n"); }

int main(void) {
    void (*table[3])(void) = { start, stop, pause };
    for (int i = 0; i < 3; i++) table[i]();
    return 0;
}

typedef упрощает таблицу

Использование typedef для типа указателя на функцию делает объявление таблицы коротким и понятным.

#include <stdio.h>

typedef int (*BinOp)(int,int);

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

int main(void) {
    BinOp ops[] = { add, sub };
    printf("%d\n", ops[0](10, 4));
    return 0;
}

Сопоставление символов с функциями

Свяжите каждый символ оператора с его функцией в параллельных массивах или таблице структур, чтобы находить функцию по имени.

#include <stdio.h>

typedef int (*BinOp)(int,int);

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

int main(void) {
    char syms[] = {'+', '-'};
    BinOp ops[] = { add, sub };
    char want = '-';
    for (int i = 0; i < 2; i++)
        if (syms[i] == want) printf("%d\n", ops[i](9, 2));
    return 0;
}

Таблица команд на основе структуры

Объедините имя и обработчик в структуру, а затем создайте массив таких структур. Это классический шаблон таблицы команд.

#include <stdio.h>
#include <string.h>

typedef struct {
    const char *name;
    void (*run)(void);
} Command;

void hello(void){printf("hi\n");}
void bye(void){printf("bye\n");}

int main(void) {
    Command cmds[] = {{"hello", hello}, {"bye", bye}};
    const char *input = "bye";
    for (int i = 0; i < 2; i++)
        if (strcmp(cmds[i].name, input) == 0) cmds[i].run();
    return 0;
}

Проверка границ

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

#include <stdio.h>

typedef int (*Fn)(int);
int sq(int x){return x*x;}
int neg(int x){return -x;}

int main(void) {
    Fn table[] = { sq, neg };
    int n = 2;
    int idx = 5;
    if (idx >= 0 && idx < n) printf("%d\n", table[idx](3));
    else printf("index out of range\n");
    return 0;
}

Конечные автоматы

Таблицы диспетчеризации управляют конечными автоматами: каждое состояние представлено указателем на функцию, а обработчики возвращают индекс следующего состояния.

#include <stdio.h>

int state_a(void){ printf("A\n"); return 1; }
int state_b(void){ printf("B\n"); return -1; }

int main(void) {
    int (*states[2])(void) = { state_a, state_b };
    int s = 0;
    while (s >= 0) s = states[s]();
    return 0;
}

Диспетчеризация по типу плагинов

Если регистрировать обработчики в таблице, новое поведение можно добавить новой записью, не изменяя большой оператор switch.

#include <stdio.h>

typedef void (*Handler)(int);
void log_low(int v){printf("low %d\n", v);}
void log_high(int v){printf("high %d\n", v);}

int main(void) {
    Handler handlers[] = { log_low, log_high };
    int level = 1;
    handlers[level](7);
    return 0;
}

Обработчик по умолчанию

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

#include <stdio.h>

typedef void (*Fn)(void);
void known(void){printf("known\n");}
void fallback(void){printf("unknown command\n");}

int main(void) {
    Fn table[] = { known };
    int n = 1, code = 9;
    Fn f = (code >= 0 && code < n) ? table[code] : fallback;
    f();
    return 0;
}

Почему таблицы хорошо масштабируются

Таблицы диспетчеризации превращают логику ветвления в поиск по данным. Добавление вариантов означает добавление данных, поэтому код остаётся плоским и быстрым.

#include <stdio.h>

typedef int (*Fn)(int);
int a(int x){return x+1;}
int b(int x){return x*2;}
int c(int x){return x*x;}

int main(void) {
    Fn t[] = { a, b, c };
    for (int i = 0; i < 3; i++) printf("%d ", t[i](4));
    printf("\n");
    return 0;
}

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете таблицы указателей на функции.

Итоги

Вы изучили шаблоны диспетчеризации с таблицами указателей на функции:

  • Храните указатели на функции в массиве и выбирайте их по индексу.
  • Они заменяют длинные цепочки switch и масштабируются за счёт добавления данных.
  • Используйте typedef и таблицы команд на основе структур для большей ясности.
  • Всегда проверяйте индекс на выход за границы и предоставляйте обработчик по умолчанию.

Часто задаваемые вопросы

Урок «Таблицы указателей на функции» бесплатный?

Да — полный текст урока «Таблицы указателей на функции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.

Чему я научусь в уроке «Таблицы указателей на функции»?

Шаблоны диспетчеризации Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C Academy?

Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Таблицы указателей на функции»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C Academy?

Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Объявление указателей на функции
  2. Передача функций
  3. qsort с компараторами
  4. Таблицы указателей на функции
← Назад к C Academy