Puntatori di funzioni nella programmazione in C con esempi

Sommario:

Anonim

I puntatori danno grandi possibilità alle funzioni 'C' che ci limitiamo a restituire un valore. Con i parametri del puntatore, le nostre funzioni ora possono elaborare i dati effettivi anziché una copia dei dati.

Per modificare i valori effettivi delle variabili, l'istruzione chiamante passa gli indirizzi ai parametri del puntatore in una funzione.

In questo tutorial imparerai-

  • Esempio di puntatori di funzioni
  • Funzioni con parametri array
  • Funzioni che restituiscono una matrice
  • Puntatori di funzione
  • Matrice di puntatori a funzione
  • Funzioni che utilizzano puntatori vuoti
  • Puntatori a funzione come argomenti

Esempio di puntatori di funzioni

Ad esempio, il programma successivo scambia due valori di due:

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;}}

Produzione:

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

Il programma scambia i valori effettivi delle variabili perché la funzione accede ad essi tramite indirizzo utilizzando i puntatori. Qui discuteremo il processo del programma:

  1. Dichiariamo la funzione responsabile dello scambio dei due valori delle variabili, che accetta due puntatori interi come parametri e restituisce qualsiasi valore quando viene chiamato.
  2. Nella funzione principale, dichiariamo e inizializziamo due variabili intere ('m' e 'n') quindi stampiamo i loro valori rispettivamente.
  3. Chiamiamo la funzione swap () passando l'indirizzo delle due variabili come argomenti utilizzando il simbolo e commerciale. Successivamente, stampiamo i nuovi valori scambiati delle variabili.
  4. Qui definiamo il contenuto della funzione swap () che accetta due indirizzi di variabili intere come parametri e dichiariamo una variabile intera temporanea utilizzata come terza casella di memorizzazione per salvare una delle variabili di valore che verranno inserite nella seconda variabile.
  5. Salva il contenuto della prima variabile indicata da "a" nella variabile temporanea.
  6. Memorizza la seconda variabile indicata da b nella prima variabile indicata da a.
  7. Aggiorna la seconda variabile (indicata da b) in base al valore della prima variabile salvata nella variabile temporanea.

Funzioni con parametri array

In C, non possiamo passare un array per valore a una funzione. Considerando che, un nome di array è un puntatore (indirizzo), quindi passiamo semplicemente un nome di array a una funzione che significa passare un puntatore all'array.

Ad esempio, consideriamo il seguente programma:

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);}

Produzione:

 Total summation is 471

Qui spiegheremo il codice del programma con i suoi dettagli

  1. Dichiariamo e definiamo la funzione add_array () che accetta un indirizzo di array (puntatore) con il numero di elementi come parametri e restituisce la somma totale accumulata di questi elementi. Il puntatore viene utilizzato per iterare gli elementi dell'array (usando la notazione p [k]) e accumuliamo la somma in una variabile locale che verrà restituita dopo aver iterato l'intero array di elementi.
  2. Dichiariamo e inizializziamo un array intero con cinque elementi interi. Stampiamo la somma totale passando il nome dell'array (che funge da indirizzo) e la dimensione dell'array alla funzione chiamata add_array () come argomenti.

Funzioni che restituiscono una matrice

In C, possiamo restituire un puntatore a un array, come nel seguente programma:

#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);}

Produzione:

12345

E qui discuteremo i dettagli del programma

  1. Definiamo e dichiariamo una funzione che restituisce un indirizzo di array contenente un valore intero e non ha preso alcun argomento.
  2. Dichiariamo un puntatore intero che riceve l'array completo costruito dopo che la funzione è stata chiamata e stampiamo il suo contenuto iterando l'intero array a cinque elementi.

Si noti che un puntatore, non un array, è definito per memorizzare l'indirizzo dell'array restituito dalla funzione. Notare anche che quando una variabile locale viene restituita da una funzione, dobbiamo dichiararla come statica nella funzione.

Puntatori di funzione

Poiché sappiamo per definizione che i puntatori puntano a un indirizzo in qualsiasi posizione di memoria, possono anche puntare all'inizio del codice eseguibile come funzioni in memoria.

Un puntatore a una funzione viene dichiarato con *, l'istruzione generale della sua dichiarazione è:

return_type (*function_name)(arguments)

Devi ricordare che le parentesi attorno a (* nome_funzione) sono importanti perché senza di esse, il compilatore penserà che nome_funzione stia restituendo un puntatore di tipo_ritorno.

Dopo aver definito il puntatore alla funzione, dobbiamo assegnarlo a una funzione. Ad esempio, il programma successivo dichiara una funzione ordinaria, definisce un puntatore a funzione, assegna il puntatore a funzione alla funzione ordinaria e successivamente chiama la funzione tramite il puntatore:

#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");} 

Produzione:

HiHiHi

  1. Definiamo e dichiariamo una funzione standard che stampa un testo Hi k volte indicato dal parametro times quando la funzione viene chiamata
  2. Definiamo una funzione puntatore (con la sua dichiarazione speciale) che accetta un parametro intero e non restituisce nulla.
  3. Inizializziamo la nostra funzione di puntatore con Hi_function, il che significa che il puntatore punta a Hi_function ().
  4. Piuttosto che chiamare la funzione standard toccando il nome della funzione con argomenti, chiamiamo solo la funzione puntatore passando il numero 3 come argomenti, e il gioco è fatto!

Tieni presente che il nome della funzione punta all'indirizzo iniziale del codice eseguibile come un nome di matrice che punta al suo primo elemento. Pertanto, istruzioni come function_ptr = & Hi_function e (* funptr) (3) sono corrette.

NOTA: non è importante inserire l'operatore indirizzo & e l'operatore di riferimento indiretto * durante l'assegnazione e la chiamata di funzione.

Matrice di puntatori a funzione

Un array di puntatori a funzione può svolgere un ruolo switch o if per prendere una decisione, come nel programma successivo:

#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

Qui, discutiamo i dettagli del programma:

  1. Dichiariamo e definiamo quattro funzioni che accettano due argomenti interi e restituiscono un valore intero. Queste funzioni aggiungono, sottraggono, moltiplicano e dividono i due argomenti relativi a quale funzione viene chiamata dall'utente.
  2. Dichiariamo 4 numeri interi per gestire rispettivamente operandi, tipo di operazione e risultato. Inoltre, dichiariamo un array di quattro puntatori a funzione. Ogni puntatore a funzione dell'elemento array accetta due parametri interi e restituisce un valore intero.
  3. Assegniamo e inizializziamo ogni elemento dell'array con la funzione già dichiarata. Ad esempio, il terzo elemento che è il terzo puntatore a funzione punterà alla funzione di operazione di moltiplicazione.
  4. Cerchiamo operandi e tipo di operazione dall'utente digitato con la tastiera.
  5. Abbiamo chiamato l'elemento dell'array appropriato (puntatore alla funzione) con argomenti e memorizziamo il risultato generato dalla funzione appropriata.

L'istruzione int (* ope [4]) (int, int); definisce l'array di puntatori a funzione. Ogni elemento della matrice deve avere gli stessi parametri e il tipo restituito.

Il risultato dell'istruzione = ope [scelta] (x, y); esegue la funzione appropriata in base alla scelta effettuata dall'utente. I due interi inseriti sono gli argomenti passati alla funzione.

Funzioni che utilizzano puntatori vuoti

I puntatori Void vengono utilizzati durante le dichiarazioni di funzione. Usiamo un tipo di ritorno void * che consente di restituire qualsiasi tipo. Se assumiamo che i nostri parametri non cambino quando passiamo a una funzione, lo dichiariamo come const.

Per esempio:

 void * cube (const void *); 

Considera il seguente programma:

#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;}

Risultato:

 4 cubed is 64 

Qui discuteremo i dettagli del programma:

  1. Definiamo e dichiariamo una funzione che restituisce un valore intero e accetta un indirizzo di variabile non modificabile senza un tipo di dati specifico. Calcoliamo il valore del cubo della variabile di contenuto (x) puntata dal puntatore num, e poiché si tratta di un puntatore void, dobbiamo digitare cast su un tipo di dati intero utilizzando un puntatore di notazione specifica (* tipo di dato) e restituiamo il valore del cubo.
  2. Dichiariamo l'operando e la variabile di risultato. Inoltre, inizializziamo il nostro operando con il valore "4."
  3. Chiamiamo la funzione cubo passando l'indirizzo dell'operando e gestiamo il valore restituito nella variabile risultato

Puntatori a funzione come argomenti

Un altro modo per sfruttare un puntatore a funzione passandolo come argomento a un'altra funzione a volte chiamata "funzione di richiamata" perché la funzione ricevente "la richiama".

Nel file di intestazione stdlib.h, la funzione Quicksort "qsort ()" utilizza questa tecnica che è un algoritmo dedicato all'ordinamento di un array.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void * base: puntatore void all'array.
  • size_t num: il numero dell'elemento dell'array.
  • size_t width La dimensione dell'elemento.
  • int (* compare (const void *, const void *): puntatore a funzione composto da due argomenti e restituisce 0 quando gli argomenti hanno lo stesso valore, <0 quando arg1 viene prima di arg2 e> 0 quando arg1 viene dopo arg2.

Il seguente programma ordina un array di numeri interi da un numero piccolo a un numero grande utilizzando la funzione 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;}

Risultato:

 13 14 48 50 52 

Qui discuteremo i dettagli del programma:

  1. Definiamo la funzione di confronto composta da due argomenti e restituisce 0 quando gli argomenti hanno lo stesso valore, <0 quando arg1 viene prima di arg2 e> 0 quando arg1 viene dopo arg2.I parametri sono un tipo di puntatori void cast al tipo di dati array appropriato (numero intero)
  2. Definiamo e inizializziamo un array intero La dimensione dell'array è memorizzata nella variabile num e la dimensione di ogni elemento dell'array è memorizzata nella variabile width usando l'operatore C predefinito sizeof ().
  3. Chiamiamo la funzione qsort e passiamo il nome dell'array, la dimensione, la larghezza e la funzione di confronto definite in precedenza dall'utente per ordinare il nostro array in ordine crescente.Il confronto verrà eseguito prendendo in ogni iterazione due elementi dell'array fino all'intero array sarà ordinato.
  4. Stampiamo gli elementi dell'array per essere sicuri che il nostro array sia ben ordinato iterando l'intero array usando il ciclo for.