אפשר הסבר?

koler

New member
אפשר הסבר?

למה משמשים מצביעים לפונקציות בc?
כלומר מה אני יכול לעשות איתם למה זה עוזר לי ברמה עקרונית?

לא כ''כ הבנתי מהמדריכים ברשת.

תודה רבה.
 

BravoMan

Active member
להרבה דברים:

בגדול, כמו שאתה יכול להעביר נתונים ממקום למקום בתוכנה שלך, ככה אתה גם יכול להעביר פונקציות.

למשל, מנגנון callback - יש לך חישוב שרץ ברקע או לולאה שממתינה לאירוע חומרה, או מנגנון אחר כלשהו שהוא מבחינתך "קופסה שחורה".

אתה מעביר לו מצביע לפונקציה והוא יקרה לה כשיהיה לו מה לדווח לך.
(ככה למשל עובד GUI).

אפשרות אחרת היא פונקציות גינריות של אלגוריתמים מוכרים:
למשל, פונקציה שמבצעת מיון יכולה לקבל כפרמטר מצביע לפונקציית השוואה, וכך היא תוכל להשוות לא רק טיפוסים פשוטים שניתן להשוות עם < >, אלא גם מבנים מורכבים שהמשתמש הגדיר.

וכמובן שאפשר להשתמש בזה למימוש של מחלקות ועצמים - אתה יכול לבנות מחלקה ב-C ע"י מבנה נתונים שמחזיק לא רק מידע אלא גם מצביעים לפונקציות רלוונטיות, וניתן אפילו לממש פולימורפיזם (ע"י טבלת פונקציות ווירטואליות, מה ש-++C עושה בשבילך אוטומטית מאחורי הקלעים).

עוד שימוש הוא טעינה דינמית של פונקציות מספריות דינמיות (DLL, so וכו'). ניתן להשתמש בזה ליצירת מערכות פלאגינים ועוד.
 

הפרבולה

New member
זה נוח למשל לממש "מכונת מצבים"

יש קבוצה של פונקציות ( מצבים ). ויש פוינטר לפונקציה ההתחלתית

בכל מחזור התוכנית קופצת לפונקציה שאליה מצביע הפוינטר, והפונקציה מציבה לתוך הפוינטר את הכתובת של הפונקציה ( המצב ) הבאה שיש לבצע במחזור הבא.

דוגמה:

#include <iostream>
#include <conio.h>

bool stateA();
bool stateB();
bool stateC();
bool (*pstatefunc)() = stateA; // init pointer fo function

bool stateA()
{
printf("execute stateA...\n");
int c=_getch();
switch(c){
case 'a': break;
case 'b': pstatefunc=stateB; break;
case 'c': pstatefunc=stateC; break;
default: return 0; // exit program
}
return 1;
}

bool stateB()
{
printf("execute stateB...\n");
int c=_getch();
switch(c){
case 'a': pstatefunc=stateA; break;;
case 'b': break;
case 'c': pstatefunc=stateC; break;
default: return 0; // exit program
}
return 1;
}

bool stateC()
{
printf("execute stateC...\n");
int c=_getch();
switch(c){
case 'a': pstatefunc=stateA; break;;
case 'b': pstatefunc=stateB; break;
case 'c': break;
default: return 0; // exit program
}
return 1;
}

int main(int argc, char *argv[])
{
while(1){
if( !pstatefunc() )
{
break;
}
}
}
 

nocgod

New member
2 דוגמאות בתרגיל אחד

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ARR_SIZE 10
#define SCALE 1000

void sort(void** arr, size_t size, int (*comperator)(void* elem_1, void* elem_2));
int intDescending(void* elem_1, void* elem_2);
int intAscending(void* elem_1, void* elem_2);

void printArray(void** arr, size_t size, void (*printer)(void* element));
void intPrinter(void* element);

int main(int argc, char** argv)
{
int arr[ARR_SIZE];
int i;

srand((unsigned)time(NULL));

for (i = 0; i < ARR_SIZE; i++)
{
arr = (rand() % SCALE) + 1; // fill up with numbers [1, 1000]
}

printf("Random order: ");
/* notice the same printArray function can print different types of arrays */
printArray((void**)arr, ARR_SIZE, intPrinter);
printf("Descending order: ");
/* notice the same sorting function to sort ascending and descending */
sort((void**)arr, ARR_SIZE, intDescending);
printArray((void**)arr, ARR_SIZE, intPrinter);
printf("Ascending order: ");
/* notice the same sorting function to sort ascending and descending */
sort((void**)arr, ARR_SIZE, intAscending);
printArray((void**)arr, ARR_SIZE, intPrinter);
return 0;
}

/* simple bubble sort implementation */
void sort(void* arr[], size_t size, int (*comperator)(void* elem_1, void* elem_2))
{
int i;
int j;
void* temp;

for(i = 0; i < size; i++)
{
for (j = i; j < size; j++)
{
/* notice how I use only 1 sorting implementation with different comperators */
if (comperator(arr, arr[j]) >= 1)
{
temp = arr;
arr = arr[j];
arr[j] = temp;
}
}
}
}

int intDescending(void* elem_1, void* elem_2)
{
return (int)elem_2 - (int)elem_1;
}

int intAscending(void* elem_1, void* elem_2)
{
return (int)elem_1 - (int)elem_2;
}

void printArray(void* arr[], size_t size, void (*printer)(void* element))
{
int i;
printf("[");
for (i = 0; i < size; i++)
{
printer(arr);
if (i != size -1)
{
printf(", ");
}
}
printf("]\n");
}

void intPrinter(void* element)
{
printf("%d", (int)element);
}
 
תשובה אחת מתוך רבות

כשאתה קורא לפונקציה אתה מעתיק לתוכה את הפרמטרים שלה.
זה יכול להיות תהליך מאוד ארוך.
במקום זה אתה יכול להצביע למקום שבו נמצאים כבר המשתנים בתוך מבנה.
 
למעלה