نقطه عطف عملکرد در C یک ویژگی پیچیده و بسیار عملی است که به توسعه دهندگان برای پیاده سازی مکانیسم های callback – توابع به عنوان استدلال به دیگر توابع منتقل می شوند و بعداً در پاسخ به رویدادها یا شرایط ذکر می شوند. این تکنیک در برنامه نویسی مبتنی بر رویداد، طراحی کتابخانه و توسعه API، ارائه انعطاف پذیری و کد استفاده می شود.

درک نقاط عطف عملکرد در C

یک اشاره کننده تابع یک متغیر است که آدرس حافظه یک تابع را ذخیره می کند.بر خلاف اشاره کنندگان منظم که به داده ها اشاره می کنند، اشاره کننده های تابع به کد اجرایی اشاره می کنند.

int (*funcPtr)(int, int);

این امر به عنوان یک اشاره گر به دو پارامتر (FLT:2) و بازگشت به یک (FLT:3) در اطراف (FLT:4) ضروری است؛ بدون آنها، تابع بازگشت به نقطه عطفی را اعلام می کند.

int add(int a, int b) { return a + b; }
funcPtr = add; // or &add

دعوت از طریق نقطه به همان اندازه ساده است:

int result = funcPtr(5, 3); // calls add(5, 3)

نقاط عطف تابع تایپ می شوند: امضای اشاره گر باید دقیقاً با امضای تابع مشخص مطابقت داشته باشد.

استفاده مشترک برای Pointers

  • فراخوانی تابع - تمرکز اصلی این مقاله است.
  • ماشین های دولتی - جداول نقطه عطف تابع انتقال.
  • معماری یا راننده [FLT 1] - بارگذاری پویا از توابع.
  • [[۱] [۱۰] استدلال های مقایسه کننده [[۱۰]] [۱۰] [۱]]] - در توابع کتابخانه استاندارد مانند استفاده می شود.
  • (فَلَّهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُوا مَهُمَهُمَهُمَهُوا بِهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمَهُمْهُهُهُهُهُمْهُهُمْهُهُوا مَهُمَهُمَهُمَهُمَهُمْهُمْهُوَهُمَهُوَهُوَهُوا مَهُهُمَهُوا مَهُمَهُمَهُمَهُمَهُوا مَهُوَهُمَهُوَهُوَهُمَهُوَهُوَهُمَهُوَهُمَهُوَهُم

پیاده سازی Callbacks با Pointers تابع

callback تابعی است که آدرسش به تابع دیگری منتقل می شود و اجازه می دهد تابع دریافت کننده تماس را در یک زمان مناسب فراخوانی کند.این تماس گیرنده را از جزئیات اجرای جدا می کند و طراحی مدولار را ترویج می کند.

#include <stdio.h>

void executeOperation(int a, int b, int (*operation)(int, int)) {
 int result = operation(a, b);
 printf("Result: %d\n", result);
}

int add(int x, int y) { return x + y; }
int multiply(int x, int y) { return x * y; }

int main() {
 executeOperation(5, 3, add);
 executeOperation(5, 3, multiply);
 return 0;
}

در اینجا [FLT 11 ] یک تابع را می پذیرد (FLT:12) و آن را با [FLT13 ] و فراخوان می کند، این الگو به طور گسترده در چارچوب های رابط کاربری گرافیکی (GUI) استفاده می شود، همانطور که I / O، و سیستم مدیریت رویداد.

Callback با User Field

اغلب callbacks نیاز به داده های اضافی فراتر از پارامترهای ثابت دارد.یک تکنیک مشترک این است که یک نقطه عطف به callback را منتقل کنید:

typedef void (*Callback)(int event, void* context);

void registerCallback(Callback cb, void* ctx) {
 // store cb and ctx internally
 // later, invoke:
 cb(EVENT_TIMER, ctx);
}

void myEventHandler(int event, void* data) {
 int* value = (int*)data;
 printf("Event %d, value %d\n", event, *value);
}

int main() {
 int myData = 42;
 registerCallback(myEventHandler, &myData);
 return 0;
}

این الگو در کتابخانه هایی مانند GLib (GTK+) استفاده می شود که در آن callbacks داده های کاربر را از طریق یک (FLT:17) حمل می کند.

انواع مختلف برای وضوح و حفظ قابلیت

اعلان های اشاره کننده تابع می توانند بدون علامت، به ویژه با امضاهای پیچیده، تبدیل شوند. قابلیت خواندن و ساده سازی نگهداری:

typedef int (*Operation)(int, int);

void execute(Operation op, int a, int b) {
 if (op) {
 printf("Result: %d\n", op(a, b));
 }
}

اکنون [FLT 20] یک نام نوع تمیز است، این به ویژه هنگامی مفید است که چندین تابع callback در پایگاه های کد بزرگتر استفاده می شود.

قرص های معمول و بهترین روش ها

  • (پیش از آنکه از آن استفاده کنید، به جای آن، از آن استفاده کنید.
  • [[۱] [۱۰] [۱۰] [۱۰] [۱]] [۱]]] [۱]] [۱]] [۱]] [۱]] [۱]] [۱]] [۱]] [۱۰]] [۱]] [۱]] [۱]]] [۱]] [۱]]] [۳]] [۱] [۱]]] [۳] [۱] [۱] [۱] [۳]] [۱] [۵] [۱] [۱] [۱] [۱] [۱]]]] [۱] [۳]] [۱]]] [۱]]]]] [۱]]]]] [۳] [۳] [۳] [۱] [۳] [۳] [۱] [۳] [۳] [۱] [۱] [۳]] [۳] [۱] [۳] [۱]]]] [۱] [۱] [۱]]] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۳]]]] [۱] [۱]] [۱] [۱
  • اختلاف های کنوانسیون - در برخی از سیستم عامل ها، به ویژه هنگامی که مخلوط کردن کتابخانه های C با زبان های دیگر، کنوانسیون های تماس باید مطابقت داشته باشند (به عنوان مثال، در ویندوز).
  • (اگر از چند رشته استفاده شود، از آن استفاده کنید و یا به صورت صحیح و صحیحی از آن استفاده کنید.
  • ] عمر اشاره کنندگان زمینه - نقطه مرجع متن به یک فراخوانی منتقل می شود باید برای تمام مدت اعتبار باقی بماند که callback ممکن است استفاده شود حافظه استاتیک یا انبوه در صورت لزوم.

الگوهای پیشرفته: آرایه های نقاط عطف عملکرد

اپراتورهای تابع را می توان در آرایه ها ذخیره کرد تا جداول ارسالی ایجاد کنند، ماشین های حالت تمیز یا فرماندار را فعال کنند.

typedef int (*Operation)(int, int);

int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }
int mul(int x, int y) { return x * y; }
int divide(int x, int y) { return y ? x / y : 0; }

Operation operations[] = { add, sub, mul, divide };
const char* opNames[] = {"add", "sub", "mul", "div"};

int main() {
 int a = 10, b = 2;
 for (int i = 0; i < 4; ++i) {
 printf("%s: %d\n", opNames[i], operations[i](a, b));
 }
 return 0;
}

این الگو غیر قابل انکار است و از زنجیره های طولانی (FLT 25) یا [FLT 26] دوری می کند.

مقایسه با زبان های دیگر

زبان هایی مانند C++ از نشانگرهای تابع استفاده می کنند، اما همچنین نشانگرهای سرگرم کننده، lambdas و [FLT 27] را برای انعطاف پذیری بیشتر ارائه می دهند، با این حال، C همچنان پایه و اساس است و درک نقاط تابع برای کار با API های سیستم عامل (به عنوان مثال، POSIX سیگنال های مسئول، سیستم های جاسازی شده، و کد استاندارد کتابخانه C از آن استفاده می کند.

ویژگی های Performance

تابع Pointer غیرمستقیمion دارای حداقل سربار است - به طور معمول یک نقطه عطف منفرد و یک تماس غیر مستقیم. CPU های مدرن با پیش بینی شاخه های غیر مستقیم به طور موثر اداره می کنند، اما استفاده بیش از حد در حلقه های تنگ ممکن است باعث کاهش جزئی در اکثر سناریوها، خوانایی و حفظ قابلیت ها به مراتب بیشتر از هر هزینه عملکردی است.

نمونه های واقعی جهانی Callbacks در C

  • [[۱] [۱۰] [۱] [۱۰] [۱] [۱۰]] [۱]] [۱۰] [۱]] [۱]] [۱]] [۱]] [۱] [۱]] [۱]] [۱] [۱] [۱]] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱]]] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [
  • [در این باره] [و [از این رو] [[[۱]]] [[۱۰]]] [[۳]]] [[۳]]] [۱]]] [[۳]]]] [[۱۰]]]] [[۳]]] [۱]] [۱] [۱]] [۱] [۱] [۱]] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۱]]]]] [۱]]]] [۱] [۳] [۳] [۱] [۱] [۳] [۱] [۳] [۳] [۱] [۱] [۱] [۳] [۳] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۳] [۳] [۱] [۱] [۳] [۱] [۱] [۳] [۱] [
  • حلقه های در کتابخانه های سطح پایین - libev، libuv و کتابخانه های رویداد مشابه استفاده از callbacks برای I / O، تایمر و سیگنال.
  • Comparison در مرتب سازی الگوریتم ها [FLT 1] - و از کتابخانه استاندارد C.
  • ] ابزار ابزار [FLT: ] - Gtk + و EFL (کتابخانه های بنیاد نور) استفاده از callbacks به طور گسترده ای برای پردازش رویداد ویجت.

نتیجه گیری

نقطه عطف برنامه نویسی C، فعال کردن مکانیسم های callback که انعطاف پذیری، مدولار بودن و کد استفاده می کنند، با درک اعلامیه خود، استفاده از با تایپه ها و الگوهای پیشرفته مانند جداول ارسال، شما می توانید سیستم های قوی و قابل نگهداری را طراحی کنید: همیشه به بهترین شیوه ها پایبند باشید: بررسی برای ، اطمینان از سازگاری امضا، مدیریت زمینه های عمر و اسناد به وضوح می توانید با استفاده از این مهارت های قدرت کامل تماس بگیرید.

در این کتاب به عنوان مثال به |C]] اشاره کنید و به بررسی نحوه استفاده از اشاره کنندگان در |C]] مراجعه کنید. یک شیرجه عمیق تر به برنامه نویسی مبتنی بر رویداد با callbacks می تواند در این مقاله ویکی پدیا در مورد حلقه های رویداد [FLT5:5] یافت شود.