Показивачи пружају велике могућности функцијама 'Ц' које смо ограничени да вратимо једну вредност. Помоћу параметара показивача, наше функције сада могу обрађивати стварне податке, а не копију података.
Да би се измениле стварне вредности променљивих, позивни израз преноси адресе параметрима показивача у функцији.
У овом упутству ћете научити-
- Пример показивача на функције
- Функције са параметрима низа
- Функције које враћају низ
- Показивачи функција
- Низ показивача на функције
- Функције помоћу празних показивача
- Показатељи на функције као аргументи
Пример показивача на функције
На пример, следећи програм замењује две вредности две:
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
Програм замењује стварне вредности променљивих јер им функција приступа помоћу адресе помоћу показивача. Овде ћемо разговарати о програмском процесу:
- Декларишемо функцију одговорну за замену две променљиве вредности, која узима два целобројна показивача као параметре и враћа било коју вредност када је позвана.
- У главној функцији декларишемо и иницијализујемо две целобројне променљиве ('м' и 'н'), а затим исписујемо њихове вредности.
- Функцију свап () позивамо тако што прослеђујемо адресу две променљиве као аргументе користећи симбол амперсанд. Након тога, исписујемо нове замењене вредности променљивих.
- Овде дефинишемо садржај функције свап () који узима две адресе целобројне променљиве као параметре и декларише привремену целобројну променљиву која се користи као трећи оквир за складиштење да би сачувао једну од променљивих вредности које ће бити стављене у другу променљиву.
- У привремену променљиву сачувајте садржај прве променљиве на коју је указано „а“.
- Спремите другу променљиву уперену са б у прву променљиву уперену са а.
- Ажурирајте другу променљиву (на коју указује б) вредношћу прве променљиве сачуване у привременој променљивој.
Функције са параметрима низа
У Ц не можемо функцију проследити низ по вредности. Док је име низа показивач (адреса), тако да само прослеђујемо име низа функцији која значи прослеђивање показивача на низ.
На пример, разматрамо следећи програм:
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
Овде ћемо објаснити програмски код са његовим детаљима
- Декларишемо и дефинишемо функцију адд_арраи () која као низ узима адресу низа (показивач) са бројем његових елемената и враћа укупан акумулирани збир ових елемената. Показивач се користи за итерацију елемената низа (користећи нотацију п [к]), а сабирање сакупљамо у локалној променљивој која ће бити враћена након итерације читавог низа елемената.
- Декларишемо и иницијализујемо целобројни низ са пет целобројних елемената. Укупан зброј исписујемо прослеђивањем имена низа (који делује као адреса) и величине низа функцији адд_арраи () која се назива аргументом.
Функције које враћају низ
У Ц-у можемо вратити показивач на низ, као у следећем програму:
#includeint * 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
И овде ћемо разговарати о детаљима програма
- Дефинишемо и декларишемо функцију која враћа адресу низа која садржи целобројну вредност и није узела ниједан аргумент.
- Декларишемо целобројни показивач који прима комплетни низ изграђен након позива функције и његов садржај исписујемо итерацијом читавог низа од пет елемената.
Приметите да је показивач, а не низ, дефинисан за чување адресе низа коју враћа функција. Такође приметите да када се локална променљива враћа из функције, морамо је прогласити статичном у функцији.
Показивачи функција
Као што по дефиницији знамо да показивачи упућују на адресу на било којој меморијској локацији, они такође могу да покажу на почетак извршног кода као функције у меморији.
Показивач на функцију декларисан је са *, општа изјава његове декларације је:
return_type (*function_name)(arguments)
Морате имати на уму да су заграде око (* име_функције) важне јер ће без њих компајлер мислити да функција_име враћа показивач ретурн_типе.
Након дефинисања показивача функције, морамо га доделити функцији. На пример, следећи програм декларише обичну функцију, дефинише показивач функције, додељује показивач функције обичној функцији и након тога позива функцију кроз показивач:
#includevoid 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
- Дефинишемо и декларишемо стандардну функцију која исписује Хи текст к пута означена параметром пута када је функција позвана
- Дефинишемо функцију показивача (са њеном посебном декларацијом) која узима целобројни параметар и не враћа ништа.
- Функцију показивача иницијализујемо функцијом Хи_, што значи да показивач показује на функцију Хи_функција ().
- Уместо да зовемо стандардну функцију залепљивањем имена функције аргументима, ми позивамо само функцију показивача предавањем броја 3 као аргумента, и то је то!
Имајте на уму да име функције показује на почетну адресу извршног кода попут имена низа које упућују на њен први елемент. Стога су упутства попут фунцтион_птр = & Хи_фунцтион и (* фунптр) (3) тачна.
НАПОМЕНА: Није важно убацити оператор адресе & и посредник * током додељивања функције и позива функције.
Низ показивача на функције
Низ показивача на функције може играти прекидач или улогу израза иф за доношење одлуке, као у следећем програму:
#includeint 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
Овде разговарамо о детаљима програма:
- Декларишемо и дефинишемо четири функције које узимају два целобројна аргумента и враћају целобројну вредност. Ове функције додају, одузимају, множе и деле два аргумента у вези са функцијом коју корисник позива.
- Декларишемо 4 целобројне вредности за обраду операнда, типа операције и резултата. Такође, декларишемо низ од четири показивача на функцију. Сваки показивач функције елемента низа узима два целобројна параметра и враћа целу вредност.
- Додељујемо и иницијализујемо сваки елемент низа функцијом која је већ декларисана. На пример, трећи елемент који је показивач треће функције указаће на функцију операције множења.
- Операнде и тип операције тражимо од корисника који је откуцан тастатуром.
- Аргументи смо позвали одговарајући елемент низа (показивач функције) и чувамо резултат генерисан одговарајућом функцијом.
Упутство инт (* опе [4]) (инт, инт); дефинише низ показивача на функције. Сваки елемент низа мора имати исте параметре и тип повратка.
Резултат изјаве = опе [избор] (к, и); покреће одговарајућу функцију према избору који је извршио корисник Два унета цела броја су аргументи прослеђени функцији.
Функције помоћу празних показивача
Показивачи на празнине користе се током декларације функција. За враћање било ког типа користимо дозволе воид * ретурн типе. Ако претпоставимо да се наши параметри не мењају приликом преласка на функцију, декларишемо је као цонст.
На пример:
void * cube (const void *);
Размотрите следећи програм:
#includevoid* 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
Овде ћемо разговарати о детаљима програма:
- Ми дефинишемо и декларишемо функцију која враћа целобројну вредност и узима адресу непроменљиве променљиве без одређеног типа података. Израчунавамо вредност коцке променљиве садржаја (к) на коју показује показивач нум, а како је то воид показивач, морамо да је откуцамо у целобројни тип података користећи одређени показивач за запис (* дататипе) и вратимо вредност коцке.
- Декларишемо операнд и променљиву резултата. Такође, иницијализујемо наш операнд са вредношћу „4.“
- Функцију коцке позивамо прослеђивањем адресе операнда и обрађујемо повратну вредност у променљиви резултата
Показатељи на функције као аргументи
Још један начин да се користи показивач на функцију прослеђујући га као аргумент другој функцији која се понекад назива „функција повратног позива“, јер је функција пријема „позива“.
У заглавној датотеци стдлиб.х, функција Куицксорт "ксорт ()" користи ову технику која је алгоритам намењен за сортирање низа.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- воид * база: воид показивач на низ.
- сизе_т нум: Број елемента низа.
- сизе_т видтх Величина елемента.
- инт (* упореди (цонст воид *, цонст воид *): показивач функције састављен од два аргумента и враћа 0 када аргументи имају исту вредност, <0 када арг1 долази пре арг2, и> 0 када арг1 долази после арг2.
Следећи програм сортира целобројни низ од малог до већег броја помоћу функције ксорт ():
#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
Овде ћемо разговарати о детаљима програма:
- Дефинишемо функцију упоређивања која се састоји од два аргумента и враћа 0 када аргументи имају исту вредност, <0 када арг1 долази пре арг2, и> 0 када арг1 долази после арг2. Параметри су тип празних показивача преливен у одговарајући тип података низа (цео број)
- Дефинисемо и иницијализујемо целобројни низ Величина низа се чува у променљивој нум, а величина сваког елемента низа чува се у променљивој ширине помоћу унапред дефинисаног Ц оператора сизеоф ().
- Позивамо функцију ксорт и просљеђујемо име низа, величину, ширину и функцију поређења које је претходно дефинисао корисник како би сортирали наш низ у растућем редоследу. Поређење ће се извршити узимајући у свакој итерацији по два елемента низа све док цео низ биће сређено.
- Елементе низа исписујемо како бисмо били сигурни да је наш низ добро сортиран итерацијом читавог низа помоћу петље фор.