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

Указатели на функции в C: практические примеры и лучшие практики

Указатели на функции раскрывают мощные возможности в C, позволяя функциям манипулировать данными напрямую через адреса памяти вместо копирования значений. Передавая адреса указателям-параметрам, функция может изменять исходные переменные, реализуя паттерны вроде обмена на месте, динамических обратных вызовов и функций высшего порядка.

Пример указателей на функции

Классическая процедура swap демонстрирует, как функция может обменять значения двух переменных, оперируя их адресами.

void swap (int *a, int *b); int main() { int m = 25; int n = 100; printf("m is %d, n is %d\n", m, n); swap(&m, &n); printf("m is %d, n is %d\n", m, n); return 0; } void swap (int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; }

Вывод:

m is 25, n is 100 m is 100, n is 25

Указатели на функции в C: практические примеры и лучшие практики

  1. Объявите swap с двумя целочисленными указателями.
  2. Инициализируйте m и n в main и выведите их.
  3. Вызовите swap(&m, &n) для передачи адресов.
  4. Внутри swap используйте временную переменную для обмена значениями.
  5. Разыменуйте указатели для чтения/записи фактических данных.

Функции с параметрами-массивами

Массивы распадаются в указатели при передаче в функции. Следующая программа суммирует элементы массива, итерируясь по указателю.

int add_array (int *a, int num_elements); int main() { int Tab[5] = {100, 220, 37, 16, 98}; printf("Total summation is %d\n", add_array(Tab, 5)); return 0; } int add_array (int *p, int size) { int total = 0; for (int k = 0; k < size; k++) { total += p[k]; /* эквивалентно total += *p; p++; */ } return total; }

Вывод:

 Total summation is 471

Указатели на функции в C: практические примеры и лучшие практики

  1. Определите add_array для принятия указателя и размера, возвращающей сумму.
  2. Передайте имя массива Tab (распавшийся в указатель) и его длину в функцию.

Функции, возвращающие массив

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

#include <stdio.h> int * build_array(); int main() { int *a; a = build_array(); /* получить первые 5 четных чисел */ for (int k = 0; k < 5; k++) printf("%d\n", a[k]); return 0; } int * build_array() { static int Tab[5] = {1,2,3,4,5}; return Tab; }

Вывод:

1 2 3 4 5

Указатели на функции в C: практические примеры и лучшие практики

  1. Объявите функцию, возвращающую указатель на статический массив.
  2. Используйте возвращенный указатель для итерации и печати содержимого массива.

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

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

return_type (*function_name)(arguments)

Пример: вызов процедуры через указатель.

#include <stdio.h> void Hi_function (int times); /* function */ int main() { void (*function_ptr)(int); /* function pointer */ function_ptr = Hi_function; /* assignment */ function_ptr(3); /* invocation */ return 0; } void Hi_function (int times) { for (int k = 0; k < times; k++) printf("Hi\n"); }

Вывод:

Hi Hi Hi

Указатели на функции в C: практические примеры и лучшие практики

  1. Определите обычную функцию.
  2. Объявите указатель на функцию с правильной сигнатурой.
  3. Присвойте указателю имя функции.
  4. Вызовите функцию через указатель.

Массив указателей на функции

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

#include <stdio.h> int sum(int num1, int num2); int sub(int num1, int num2); int mult(int num1, int num2); int divi(int num1, int num2); int main() { int x, y, choice, result; int (*ope[4])(int, int); ope[0] = sum; ope[1] = sub; ope[2] = mult; ope[3] = divi; printf("Enter two integer numbers: "); scanf("%d%d", &x, &y); printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: "); scanf("%d", &choice); result = ope[choice](x, y); printf("%d", result); return 0; } int sum(int x, int y) {return x + y;} int sub(int x, int y) {return x - y;} int mult(int x, int y) {return x * y;} int divi(int x, int y) {return y != 0 ? x / y : 0;}

Результат: Ввод 13 48 2 → 624

Указатели на функции в C: практические примеры и лучшие практики

  1. Определите четыре арифметические функции.
  2. Создайте массив из четырех указателей на функции с совпадающими сигнатурами.
  3. Присвойте каждый указатель соответствующей функции.
  4. Получите выбор пользователя и вызовите выбранную функцию.

Функции, использующие void-указатели

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

void * cube (const void *);

Пример программы:

#include <stdio.h> void* cube (const void* num); int main() { int x = 4; int cube_int = (int)cube(&x); printf("%d cubed is %d\n", x, cube_int); return 0; } void* cube (const void *num) { int result = (*(int *)num) * (*(int *)num) * (*(int *)num); return (void*)result; }

Результат: 4 cubed is 64

Указатели на функции в C: практические примеры и лучшие практики

  1. Определите функцию, принимающую const void указатель и возвращающую void указатель.
  2. Приведите указатель к int * для доступа к значению.
  3. Вычислите куб и приведите результат обратно к void * для возврата.

Указатели на функции как аргументы

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

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *));

Пример сортировки целочисленного массива:

#include <stdio.h> #include <stdlib.h> int compare (const void *, const void *); int main() { int arr[5] = {52, 14, 50, 48, 13}; size_t num = sizeof(arr)/sizeof(arr[0]); size_t width = sizeof(arr[0]); qsort((void *)arr, num, width, compare); for (size_t i = 0; i < num; i++) printf("%d ", arr[i]); return 0; } int compare (const void *elem1, const void *elem2) { int a = *(int *)elem1; int b = *(int *)elem2; return (a - b); }

Результат: 13 14 48 50 52

Указатели на функции в C: практические примеры и лучшие практики

  1. Реализуйте compare для возврата отрицательного, нуля или положительного на основе двух целых чисел.
  2. Определите размер массива и ширину элемента с помощью sizeof.
  3. Вызовите qsort с массивом, количеством, шириной и функцией сравнения.
  4. Выведите отсортированный массив для проверки операции.

Язык C

  1. Четыре проверенных паттерна пользовательских функций в C
  2. Цикл do-while в C++: синтаксис, примеры и вложенные циклы
  3. Указатели в C++: концепции, примеры и практические применения
  4. Перегрузка операторов в C++: практическое руководство с примерами кода
  5. Функции в C++: подробное объяснение с практическими примерами кода
  6. Коллекции в C#: практическое руководство с реальными примерами
  7. Указатели в C: полное руководство по типам, использованию и лучшим практикам
  8. Мастерство метода str.count() в Python: как подсчитывать символы и подстроки с примерами
  9. Освоение лямбда-функций Python: практические примеры и лучшие практики
  10. Функция round() в Python: подробное объяснение с практическими примерами