مؤشر (برمجة)
الدعم في العديد من لغات البرمجة > لغة C ولغة C++

المؤشرات في لغة C ولغة C++ هي المتغيرات التي تخزن العناوين ويمكن أن تكون null. يسير كل مؤشر إلى نوع خاص به، ولكن يمكن للفرد التنقل بحرية بين أنواع المؤشرات، على الرغم من أن السلوك هو تطبيق معروف. يسمح نوع خاص من المؤشرات يطلق عليه «مؤشر void» بالإشارة إلى أي نوع من المتغيرات، ولكن تحده حقيقة أنه لا يمكن تتبعه مباشرةً. غالباً يمكن معالجة العنوان نفسه مباشرة بإلقاء مؤشر من وإلى نوع متكامل بحجم مناسب، على الرغم من أن النتائج هي تطبيقات معروفة ويمكن أن تتسبب في سلوكيات غير معروفة؛ بينما لا يوجد لدى معايير لغة C السابقة نوع متكامل الذي ضُمن أن يكون كبير بدرجة كافية، لغة C99 تحدد اسم uintptr_t typedef المعرَّفة في <stdint.h>، لكن لا يحتاج التطبيق لتوافرها.
تدعم لغة ++C بالكامل مؤشرات لغة السيC وتحويل نوع المتغير typecasting لغة C. كما تدعم مجموعة جديدة من مشغلات التحويل نوع المتغير typecasting للمساعدة في التقاط بعض الاشكال الخطيرة في الوقت الواحد. كما تقدم المكتبة المعيارية للغة C++ auto ptr نوع من المؤشرات الذكية الذي يمكن استخدامه في بعض المواقف كبديل آمن للمؤشرات الأولية في لغة C. كما تدعم لغة C++ شكل آخر من المرجع، مختلف عن المؤشر يطلق عليه ببساطة المرجع أو نمط المرجع.
المؤشر الحسابي هو القدرة على تعديل عنوان المؤشر المستهدف بعمليات حسابية (وكذلك مقارنات الحجم) ويقتصر على معايير اللغة للبقاء ضمن حدود كائن المصفوفة الواحدة (أو فقط بعد ذلك)، على الرغم من أن العديد من الهياكل المتكاملة ستسمح بالمزيد من التساهلات الحسابية. الإضافة أو الطرح من مؤشر يحركه بمضاعفات الحجم من نوع البيانات التي تشير إليها. على سبيل المثال، إضافة 1 إلى مؤشر قيمته 4 بايت سيزيد المؤشر بمقدار 4. وهذا له تأثير في زيادة المؤشر للإشارة إلى الكائن التالي في المصفوفة المرتبطة من الأعداد الصحية- غالباً ما تكون هذه هي النتيجة المطلوبة. لا يمكن للمؤشر الحسابي الأداء على مؤشر void لأن نوع void ليس له حجم، وبالتالي لا يمكن إضافة العنوان المشار إليه، عل الرغم من أن gcc وغيرها من المجمعات ستؤدي حسابات البايت على void* كامتداد غير معياري. للعمل مباشرةً مع وحدات البايت يلقوا عادةً المؤشرات إلى BYTE*، أو char* غير الموقعة إذا لم تُعرَّف BYTE في المكتبة المعيارية المستخدمة.
يقدم المؤشر الحسابي للمبرمج طريقة واحدة للتعامل مع مختلف الأنواع: إضافة وطرح رقم الكائن المطلوب بدلاً من الإزاحة الفعلية بوحدات البايت. (مع ذلك مؤشر char، يُعرف char بأنه الحصول دائما على حجم بقيمة 1 بايت، يسمح بإزاحة الكائن من المؤشر الحسابي إلى الممارسة ليتساوى مع إزاحة البايت الواحد) على وجه الخصوص، يوضح تعريف لغة Cصراحةً أن الصيغة a[n] حيث أن n-th كائن في المصفوفة a، تكافئ *(a+n) وهو محتوى الكائن المشار إليه بواسطة a+n. يعني هذا أن n[a] يتساوى مع n[a] ويمكن كتابة مثلاً a[3] أو [a]3 سيلج كلاهما إلى الكائن الرابع من المصفوفة A.
بينما يمكن للمؤشر الحسابي أن يكون مصدر bugs الحاسب الآلي. فإنه يميل إلى إرباك المبرمجين المبتدئين، مما يضطرهم إلى سياقات مختلفة: يمكن أن يكون تعبير حسابي عادي أو أن يكون تعبير مؤشر حسابي، وأحياناً من السهل عمل خطأ في أحدهما للآخر. واستجابة لهذا، العديد من لغات الحاسب الآلي الحديثة المتقدمة (على سبيل المثال Java) لا تسمح بالولوج المباشر إلى الذاكرة باستخدام العنوان. كذلك، تتناول لهجة لغة C الآمنة Cyclone العديد من الموضوعات المتعلقة بالمؤشرات. راجع لغة البرمجة C للمزيد من الانتقادات.
مؤشر void أو void* يُدعمه ANSI لغة C ولغة C++ كنوع مؤشر عام. مؤشر void يمكنه تخزين عنوان لأي نوع بيانات وفي لغة C يتحول ضمنياً إلى أي نوع آخر من المؤشرات أثناء المهمة، ويجب أن يلقى صراحة إذا كان تتبع المؤشر ضمني. K&R تستخدم لغة C char* لغرض «المؤشر agnostic» (قبل ANSI C).
int x = 4;
void* q = &x;
int* p = q; /* void* implicitly converted to int*: valid C, but not C++ */
int i = *p;
int j = *(int*)q; /* when dereferencing inline, there is no implicit conversion */
لا تسمح لغة C++ بالتحويل الضمني لـ void* إلى نوع آخر من المؤشرات، حتى أثناء المهمات. كان هذا قرار في التصميم لتجنب الإهمال وحتى الاشكال غير المرغوبة، مع ذلك معظم المجمعين يستخرجون التحذيرات فقط وليس الأخطاء عند مواجهة إلقاءات أخرى سيئة.
int x = 4;
void* q = &x;
// int* p = q; This fails in C++: there is no implicit conversion from void*
int* a = (int*)q; // C-style cast
int* b = static_cast<int*>(q); // C++ cast
في لغة C++، لا يوجد void& (مرجع لـ void) لاستكمال void*، لأن المراجع تتصرف مثل الأسماء المستعارة للمتغيرات التي تشير إليها، ولا يمكن وجود متغير من نوع void.