Функції Покажчики в програмуванні на Сі з прикладами

Зміст:

Anonim

Покажчики дають великі можливості функціям "С", яким ми обмежуємось повернути одне значення. Завдяки параметрам покажчика наші функції тепер можуть обробляти фактичні дані, а не копіювати дані.

Для того, щоб змінити фактичні значення змінних, оператор, що викликає, передає адреси параметрам покажчика у функції.

У цьому підручнику ви дізнаєтесь-

  • Приклади покажчиків на функції
  • Функції з параметрами масиву
  • Функції, що повертають масив
  • Покажчики функцій
  • Масив покажчиків на функції
  • Функції, що використовують порожні вказівники
  • Покажчики функцій як аргументи

Приклади покажчиків на функції

Наприклад, наступна програма міняє місцями два значення з двох:

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 100m is 100, n is 25

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

  1. Ми оголошуємо функцію, відповідальну за обмін двома значеннями змінних, яка приймає два цілочисельних покажчика як параметри і повертає будь-яке значення, коли воно викликане.
  2. У головній функції ми оголошуємо та ініціалізуємо дві цілочисельні змінні ('m' та 'n'), після чого друкуємо їх значення відповідно.
  3. Ми викликаємо функцію swap (), передаючи адресу двох змінних як аргументи, використовуючи символ амперсанда. Після цього ми друкуємо нові замінені значення змінних.
  4. Тут ми визначаємо вміст функції swap (), який приймає в якості параметрів дві цілочисельні адреси змінних, і оголошуємо тимчасову цілу змінну, яка використовується як третє поле зберігання, щоб зберегти одну зі змінних значень, яка буде додана до другої змінної.
  5. Збережіть вміст першої змінної, вказаної на 'a', у тимчасовій змінній.
  6. Зберігайте другу змінну, на яку вказує b, у першу змінну, на яку вказує a.
  7. Оновіть другу змінну (на яку вказує b) за значенням першої змінної, збереженої у тимчасовій змінній.

Функції з параметрами масиву

У C ми не можемо передавати масив за значенням функції. Тоді як ім’я масиву є покажчиком (адресою), тому ми просто передаємо ім’я масиву функції, що означає передачу вказівника на масив.

Наприклад, ми розглядаємо таку програму:

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;int k;for (k = 0; k < size; k++) {total += p[k]; /* it is equivalent to total +=*p ;p++; */}return (total);}

Вихід:

 Total summation is 471

Тут ми пояснимо код програми та її деталі

  1. Ми оголошуємо та визначаємо функцію add_array (), яка приймає в якості параметрів адресу масиву (покажчик) із номером її елементів і повертає загальне накопичене підсумовування цих елементів. Вказівник використовується для ітерації елементів масиву (за допомогою позначення p [k]), і ми накопичуємо підсумовування в локальній змінній, яка повертається після ітерації всього масиву елементів.
  2. Ми оголошуємо та ініціалізуємо цілочисельний масив з п’ятьма цілочисельними елементами. Ми друкуємо загальне підсумовування, передаючи ім'я масиву (який діє як адреса) та розмір масиву в add_array (), що називається функцією як аргументи.

Функції, що повертають масив

У C ми можемо повернути покажчик на масив, як у наступній програмі:

#include int * build_array();int main() {int *a;a = build_array(); /* get first 5 even numbers */for (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);}

Вихід:

12345

І тут ми обговоримо деталі програми

  1. Ми визначаємо та оголошуємо функцію, яка повертає адресу масиву, що містить ціле значення, і не взяла жодних аргументів.
  2. Ми оголошуємо цілочисельний покажчик, який отримує повний масив, побудований після виклику функції, і друкуємо його вміст шляхом ітерації всього масиву з п'яти елементів.

Зверніть увагу, що вказівник, а не масив, визначений для зберігання адреси масиву, що повертається функцією. Також зауважте, що коли функція повертає локальну змінну, ми повинні оголосити її як статичну у функції.

Покажчики функцій

Як ми за визначенням знаємо, що вказівники вказують на адресу в будь-якому місці пам'яті, вони також можуть вказувати на початок виконуваного коду як функції в пам'яті.

Покажчик на функцію оголошується зі знаком *, загальний виклад його оголошення:

return_type (*function_name)(arguments)

Ви повинні пам’ятати, що дужки навколо (* ім'я_функції) важливі, оскільки без них компілятор буде думати, що ім'я функції повертає покажчик return_type.

Після визначення покажчика функції ми маємо призначити його функції. Наприклад, наступна програма оголошує звичайну функцію, визначає покажчик функції, призначає покажчик функції звичайній функції і після цього викликає функцію через покажчик:

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

Вихід:

HiHiHi

  1. Ми визначаємо та оголошуємо стандартну функцію, яка друкує Hi-текст k разів, зазначених параметром times при виклику функції
  2. Ми визначаємо функцію покажчика (з її спеціальним оголошенням), яка приймає цілочисельний параметр і нічого не повертає.
  3. Ми ініціалізуємо нашу функцію вказівника за допомогою функції Hi_, що означає, що вказівник вказує на функцію Hi_function ().
  4. Замість стандартного виклику функції, пов'язуючи ім'я функції аргументами, ми викликаємо лише функцію покажчика, передаючи число 3 як аргументи, і все!

Майте на увазі, що ім’я функції вказує на початкову адресу виконуваного коду, як ім’я масиву, яке вказує на перший елемент. Отже, такі інструкції, як function_ptr = & Hi_function та (* funptr) (3), є правильними.

ПРИМІТКА: Не важливо вставляти оператор адреси & та оператор опосередкування * під час призначення функції та виклику функції.

Масив покажчиків на функції

Масив покажчиків на функції може грати перемикач або роль оператора if для прийняття рішення, як у наступній програмі:

#include int sum(int num1, int num2);int sub(int num1, int num2);int mult(int num1, int num2);int div(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] = div;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 div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2624

Тут ми обговорюємо деталі програми:

  1. Ми оголошуємо та визначаємо чотири функції, які приймають два цілочисельні аргументи і повертають ціле значення. Ці функції додають, віднімають, множать і ділять два аргументи щодо того, яку функцію викликає користувач.
  2. Ми оголошуємо 4 цілих числа для обробки операндів, типу операції та результату відповідно. Крім того, ми оголошуємо масив із чотирьох покажчиків на функції. Кожен покажчик функції елемента масиву приймає два цілі параметри і повертає ціле значення.
  3. Ми призначаємо та ініціалізуємо кожен елемент масиву за допомогою вже оголошеної функції. Наприклад, третій елемент, який є вказівником третьої функції, вказуватиме на функцію операції множення.
  4. Ми шукаємо операнди та тип операції у користувача, набраного за допомогою клавіатури.
  5. Ми викликали відповідний елемент масиву (покажчик функції) з аргументами, і ми зберігаємо результат, згенерований відповідною функцією.

Інструкція int (* ope [4]) (int, int); визначає масив покажчиків на функції. Кожен елемент масиву повинен мати однакові параметри та тип повернення.

Результат твердження = ope [вибір] (x, y); запускає відповідну функцію відповідно до вибору, зробленого користувачем. Два введені цілі числа є аргументами, переданими функції.

Функції, що використовують порожні вказівники

Покажчики порожнечі використовуються під час оголошень функцій. Ми використовуємо дозволи на повернення void * для повернення будь-якого типу. Якщо ми вважаємо, що наші параметри не змінюються при передачі функції, ми оголошуємо це як const.

Наприклад:

 void * cube (const void *); 

Розглянемо таку програму:

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

Результат:

 4 cubed is 64 

Тут ми обговоримо деталі програми:

  1. Ми визначаємо та оголошуємо функцію, яка повертає ціле значення і приймає адресу незмінної змінної без певного типу даних. Ми обчислюємо значення куба змінної змісту (x), на яку вказує вказівник num, і оскільки це порожній вказівник, ми повинні ввести його, приводячи його до цілочисельного типу даних, використовуючи конкретний нотатор (* тип даних), і повертаємо значення куба.
  2. Ми оголошуємо операнд і змінну результату. Крім того, ми ініціалізуємо наш операнд зі значенням "4."
  3. Ми викликаємо функцію куба, передаючи адресу операнда, і обробляємо значення, що повертається, у змінну результату

Покажчики функцій як аргументи

Інший спосіб використовувати покажчик функції, передаючи його як аргумент іншій функції, яку іноді називають "функцією зворотного виклику", оскільки отримуюча функція "викликає її назад".

У файлі заголовка stdlib.h функція Quicksort "qsort ()" використовує цю техніку, яка є алгоритмом, призначеним для сортування масиву.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void * base: порожній вказівник на масив.
  • size_t num: Номер елемента масиву.
  • size_t width Розмір елемента.
  • int (* порівняти (const void *, const void *): покажчик функції, що складається з двох аргументів і повертає 0, коли аргументи мають однакове значення, <0, коли arg1 стоїть перед arg2, і> 0, коли arg1 постає після arg2.

Наступна програма сортує цілочисельний масив від малого до великого числа за допомогою функції qsort ():

#include #include int compare (const void *, const void *);int main() {int arr[5] = {52, 14, 50, 48, 13};int num, width, i;num = sizeof(arr)/sizeof(arr[0]);width = sizeof(arr[0]);qsort((void *)arr, num, width, compare);for (i = 0; i < 5; i++)printf("%d ", arr[ i ]);return 0;}int compare (const void *elem1, const void *elem2) {if ((*(int *)elem1) == (*(int *)elem2)) return 0;else if ((*(int *)elem1) < (*(int *)elem2)) return -1;else return 1;}

Результат:

 13 14 48 50 52 

Тут ми обговоримо деталі програми:

  1. Ми визначаємо функцію порівняння, що складається з двох аргументів, і повертає 0, коли аргументи мають одне і те ж значення, <0, коли arg1 стоїть перед arg2, і> 0, коли arg1 постає після arg2. (ціле число)
  2. Ми визначаємо та ініціалізуємо цілочисельний масив Розмір масиву зберігається у змінній num, а розмір кожного елемента масиву зберігається у змінній ширини, використовуючи заздалегідь визначений оператор C.
  3. Ми викликаємо функцію qsort і передаємо ім'я масиву, розмір, ширину та функцію порівняння, визначені раніше користувачем, щоб відсортувати наш масив за зростанням. Порівняння буде виконано шляхом взяття в кожній ітерації двох елементів масиву, поки весь масив буде відсортовано.
  4. Ми друкуємо елементи масиву, щоб переконатися, що наш масив добре відсортований, перебираючи весь масив, використовуючи цикл for.