المؤشر (برمجة الكمبيوتر)

أعتقد أن عبارات التعيين ومتغيرات المؤشر تعد من بين "الكنوز الأكثر قيمة" في علوم الكمبيوتر.

دونالد كنوث ، البرمجة المنظمة، مع الانتقال إلى العبارات [1]

يشير المؤشر a إلى عنوان الذاكرة المرتبط بالمتغير أي أن a يحتوي على عنوان الذاكرة 1008 للمتغير b . في هذا الرسم التخطيطي، تستخدم بنية الحوسبة نفس مساحة العنوان وبدائية البيانات لكل من المؤشرات وغير المؤشرات؛ ولا ينبغي أن تكون هذه الحاجة هي الحالة.

في علوم الكمبيوتر ، المؤشر هو كائن في العديد من لغات البرمجة يخزن عنوان ذاكرة . يمكن أن يكون هذا عنوان قيمة أخرى موجودة في ذاكرة الكمبيوتر ، أو في بعض الحالات، عنوان أجهزة الكمبيوتر المخصصة للذاكرة . يشير المؤشر إلى موقع في الذاكرة، والحصول على القيمة المخزنة في هذا الموقع يُعرف باسم إلغاء الرجوع إلى المؤشر. على سبيل القياس، يمكن اعتبار رقم الصفحة في فهرس الكتاب مؤشرًا إلى الصفحة المقابلة؛ يمكن إلغاء الرجوع إلى مثل هذا المؤشر عن طريق التقليب إلى الصفحة التي تحتوي على رقم الصفحة المحدد وقراءة النص الموجود على تلك الصفحة. يعتمد الشكل والمحتوى الفعلي لمتغير المؤشر على بنية الكمبيوتر الأساسية .

يؤدي استخدام المؤشرات إلى تحسين الأداء بشكل كبير للعمليات المتكررة، مثل عبور هياكل البيانات القابلة للتكرار (على سبيل المثال السلاسل وجداول البحث وجداول التحكم وهياكل الشجرة ). على وجه الخصوص، غالبًا ما يكون نسخ المؤشرات وإلغاء مرجعيتها أرخص بكثير من نسخ البيانات التي تشير إليها المؤشرات والوصول إليها.

تُستخدم المؤشرات أيضًا لحمل عناوين نقاط الدخول للبرامج الفرعية التي يتم استدعاؤها في البرمجة الإجرائية وللربط وقت التشغيل بمكتبات الارتباط الديناميكي (DLLs) . في البرمجة الموجهة للكائنات ، تُستخدم مؤشرات الوظائف لربط الأساليب ، غالبًا باستخدام جداول الأساليب الافتراضية .

المؤشر هو تنفيذ بسيط وأكثر تحديدًا لنوع البيانات المرجعي الأكثر تجريدًا . تدعم العديد من اللغات، وخاصة اللغات منخفضة المستوى ، بعض أنواع المؤشرات، على الرغم من أن بعضها لديه قيود أكثر على استخدامها من غيرها. في حين تم استخدام "المؤشر" للإشارة إلى المراجع بشكل عام، فإنه ينطبق بشكل أكثر ملاءمة على هياكل البيانات التي تسمح واجهتها صراحةً بالتلاعب بالمؤشر (حسابيًا عبرنظرًا لأن المؤشرات تسمح بالوصول المحمي وغير المحمي إلىعناوين الذاكرة، فهناك مخاطر مرتبطة باستخدامها، خاصة في الحالة الأخيرة. غالبًا ما يتم تخزين المؤشرات البدائية بتنسيق مشابه للعدد الصحيح ؛ ومعذلك،فإنمحاولة إلغاء الإشارة أو "البحث" عن مثل هذا المؤشر الذي لا تكون قيمته عنوان ذاكرة صالحًا قد يتسبب في تعطل البرنامج (أو احتواءه على بيانات غير صالحة). لتخفيف هذه المشكلة المحتملة، كمسألة تتعلق بسلامة النوع، تعتبر المؤشرات نوعًا منفصلاً يتم تحديد معلماته حسب نوع البيانات التي تشير إليها، حتى لو كان التمثيل الأساسي عددًا صحيحًا.يمكنأيضًااتخاذتدابيرأخرى(مثلالتحققمن الصحةوالحدود)، للتحقق من أن متغير المؤشر يحتوي على قيمة هي عنوان ذاكرة صالح وضمن النطاق العددي الذي يكون المعالج قادرًا على معالجته.

تاريخ

في عام 1955، ابتكرت عالمة الكمبيوتر الأوكرانية السوفييتية كاترينا يوشينكو لغة برمجة العناوين التي جعلت من الممكن استخدام العناوين غير المباشرة وعناوين من أعلى مرتبة - على غرار المؤشرات. كانت هذه اللغة مستخدمة على نطاق واسع على أجهزة الكمبيوتر السوفييتية. ومع ذلك، لم تكن معروفة خارج الاتحاد السوفييتي وعادةً ما يُنسب إلى هارولد لوسون اختراع المؤشر في عام 1964. [2] في عام 2000، حصل لوسون على جائزة رائد الكمبيوتر من معهد مهندسي الكهرباء والإلكترونيات "لاختراع متغير المؤشر وإدخال هذا المفهوم في PL/I، وبالتالي توفير القدرة لأول مرة على معالجة القوائم المرتبطة بمرونة في لغة عالية المستوى للأغراض العامة". [3] ظهرت ورقته الرائدة حول المفاهيم في عدد يونيو 1967 من CACM بعنوان: معالجة قائمة PL/I. وفقًا لقاموس أكسفورد الإنجليزي ، ظهرت كلمة المؤشر لأول مرة مطبوعة كمؤشر مكدس في مذكرة فنية من شركة تطوير النظام .

الوصف الرسمي

في علوم الكمبيوتر ، المؤشر هو نوع من المرجع .

البيانات البدائية (أو البدائية فقط ) هي أي بيانات يمكن قراءتها أو كتابتها في ذاكرة الكمبيوتر باستخدام وصول واحد للذاكرة (على سبيل المثال، كل من البايت والكلمة هما بدائيان).

إن مجموعة البيانات (أو المجموعة فقط ) هي مجموعة من العناصر البدائية المتجاورة منطقيًا في الذاكرة والتي يتم عرضها بشكل جماعي باعتبارها بيانات واحدة (على سبيل المثال، يمكن أن تتكون المجموعة من 3 بايتات متجاورة منطقيًا، تمثل قيمها إحداثيات 3 نقاط في الفضاء). عندما تتكون المجموعة بالكامل من نفس النوع من العناصر البدائية، يمكن تسمية المجموعة بالمصفوفة ؛ بمعنى ما، تكون العناصر البدائية متعددة البايتات عبارة عن مجموعة من البايتات، وتستخدم بعض البرامج الكلمات بهذه الطريقة.

المؤشر هو مفهوم برمجة يستخدم في علوم الكمبيوتر للإشارة إلى موقع ذاكرة يخزن قيمة أو كائنًا. وهو في الأساس متغير يخزن عنوان ذاكرة متغير آخر أو بنية بيانات بدلاً من تخزين البيانات نفسها.

تُستخدم المؤشرات عادةً في لغات البرمجة التي تدعم التلاعب المباشر بالذاكرة، مثل C وC++. وهي تسمح للمبرمجين بالعمل بالذاكرة مباشرةً، مما يتيح إدارة الذاكرة بكفاءة وإنشاء هياكل بيانات أكثر تعقيدًا. باستخدام المؤشرات، يمكنك الوصول إلى البيانات الموجودة في الذاكرة وتعديلها، وتمرير البيانات بكفاءة بين الوظائف، وإنشاء هياكل بيانات ديناميكية مثل القوائم المرتبطة والأشجار والرسوم البيانية.

بعبارات أبسط، يمكنك التفكير في المؤشر باعتباره سهمًا يشير إلى مكان محدد في ذاكرة الكمبيوتر، مما يسمح لك بالتفاعل مع البيانات المخزنة في هذا الموقع.

مؤشر الذاكرة (أو المؤشر فقط ) هو بدائي، وقيمته مخصصة للاستخدام كعنوان ذاكرة؛ ويقال إن المؤشر يشير إلى عنوان ذاكرة . ويقال أيضًا إن المؤشر يشير إلى نقطة بيانات [في الذاكرة] عندما تكون قيمة المؤشر هي عنوان ذاكرة النقطة.

بشكل عام، المؤشر هو نوع من المراجع ، ويقال أن المؤشر يشير إلى بيانات مخزنة في مكان ما في الذاكرة ؛ للحصول على تلك البيانات، يجب إلغاء مرجع المؤشر . الميزة التي تفصل المؤشرات عن أنواع المراجع الأخرى هي أن قيمة المؤشر من المفترض أن يتم تفسيرها كعنوان ذاكرة، وهو مفهوم منخفض المستوى إلى حد ما.

تعمل المراجع كمستوى من مستويات الالتباس: تحدد قيمة المؤشر عنوان الذاكرة (أي البيانات) الذي سيتم استخدامه في عملية حسابية. ولأن الالتباس هو جانب أساسي من جوانب الخوارزميات، فغالبًا ما يتم التعبير عن المؤشرات كنوع أساسي من البيانات في لغات البرمجة ؛ وفي لغات البرمجة ذات النوع الثابت (أو القوي )، يحدد نوع المؤشر نوع البيانات التي يشير إليها المؤشر.

الجذور المعمارية

المؤشرات عبارة عن تجريد رقيق للغاية فوق إمكانيات التوجيه التي توفرها معظم البنيات الحديثة . في أبسط مخطط، يتم تعيين عنوان أو فهرس رقمي لكل وحدة ذاكرة في النظام، حيث تكون الوحدة عادةً إما بايتًا أو كلمة - اعتمادًا على ما إذا كانت البنية قابلة للتوجيه بالبايت أو بالكلمة - مما يحول الذاكرة بالكامل فعليًا إلى مصفوفة كبيرة جدًا. سيوفر النظام بعد ذلك أيضًا عملية لاسترداد القيمة المخزنة في وحدة الذاكرة عند عنوان معين (عادةً باستخدام سجلات الأغراض العامة للجهاز ).

في الحالة المعتادة، يكون المؤشر كبيرًا بما يكفي لاحتواء عناوين أكثر من وحدات الذاكرة الموجودة في النظام. وهذا يؤدي إلى إمكانية محاولة برنامج الوصول إلى عنوان لا يتوافق مع أي وحدة ذاكرة، إما بسبب عدم تثبيت ذاكرة كافية (أي خارج نطاق الذاكرة المتاحة) أو لأن البنية لا تدعم مثل هذه العناوين. قد تسمى الحالة الأولى، في منصات معينة مثل بنية Intel x86 ، خطأ تجزئة (segfault). الحالة الثانية ممكنة في التنفيذ الحالي لـ AMD64 ، حيث يبلغ طول المؤشرات 64 بت وتمتد العناوين إلى 48 بت فقط. يجب أن تتوافق المؤشرات مع قواعد معينة (العناوين الأساسية)، لذلك إذا تم إلغاء الرجوع إلى مؤشر غير أساسي، يثير المعالج خطأ حماية عام .

من ناحية أخرى، تحتوي بعض الأنظمة على وحدات ذاكرة أكثر من العناوين. في هذه الحالة، يتم استخدام مخطط أكثر تعقيدًا مثل تقسيم الذاكرة أو التجزئة لاستخدام أجزاء مختلفة من الذاكرة في أوقات مختلفة. تدعم التجسيدات الأخيرة لهندسة x86 ما يصل إلى 36 بتًا من عناوين الذاكرة الفعلية، والتي تم تعيينها إلى مساحة العنوان الخطية المكونة من 32 بت من خلال آلية التجزئة PAE . وبالتالي، لا يمكن الوصول إلا إلى 1/16 من إجمالي الذاكرة الممكنة في المرة الواحدة. كان مثال آخر في نفس عائلة الكمبيوتر هو الوضع المحمي المكون من 16 بتًا لمعالج 80286 ، والذي على الرغم من دعمه فقط لـ 16 ميجا بايت من الذاكرة الفعلية، يمكنه الوصول إلى ما يصل إلى 1 جيجابايت من الذاكرة الافتراضية، ولكن الجمع بين العناوين المكونة من 16 بتًا وسجلات التجزئة جعل الوصول إلى أكثر من 64 كيلوبايت في بنية بيانات واحدة أمرًا مرهقًا.

من أجل توفير واجهة متسقة، توفر بعض البنيات إدخال/إخراج مُخصص للذاكرة ، مما يسمح لبعض العناوين بالإشارة إلى وحدات الذاكرة بينما يشير البعض الآخر إلى سجلات الأجهزة الخاصة بأجهزة أخرى في الكمبيوتر. هناك مفاهيم مماثلة مثل إزاحات الملفات ومؤشرات المصفوفة ومراجع الكائنات البعيدة التي تخدم بعض الأغراض نفسها مثل العناوين الخاصة بأنواع أخرى من الكائنات.

الاستخدامات

يتم دعم المؤشرات بشكل مباشر دون قيود في لغات مثل PL/I و C و C++ و Pascal و FreeBASIC ، وبشكل ضمني في معظم لغات التجميع . تُستخدم المؤشرات بشكل أساسي لبناء المراجع ، والتي بدورها تعتبر أساسية لبناء جميع هياكل البيانات تقريبًا ، وكذلك في تمرير البيانات بين أجزاء مختلفة من البرنامج.

في لغات البرمجة الوظيفية التي تعتمد بشكل كبير على القوائم، تتم إدارة مراجع البيانات بشكل تجريدي باستخدام بنيات بدائية مثل cons والعناصر المقابلة car و cdr ، والتي يمكن اعتبارها مؤشرات متخصصة للمكونين الأول والثاني لخلية cons. يؤدي هذا إلى ظهور بعض "النكهة" الاصطلاحية للبرمجة الوظيفية. من خلال هيكلة البيانات في مثل هذه القوائم ، تسهل هذه اللغات الوسائل المتكررة لبناء ومعالجة البيانات - على سبيل المثال، من خلال الوصول بشكل متكرر إلى عناصر الرأس والذيل لقوائم القوائم؛ على سبيل المثال "أخذ car من cdr من cdr". على النقيض من ذلك، فإن إدارة الذاكرة القائمة على إلغاء مرجع المؤشر في بعض التقريبات لمجموعة من عناوين الذاكرة تسهل التعامل مع المتغيرات كفتحات يمكن تعيين البيانات فيها بشكل حتمي .

عند التعامل مع المصفوفات، تتضمن عملية البحث الحرجة عادةً مرحلة تسمى حساب العنوان والتي تتضمن إنشاء مؤشر إلى عنصر البيانات المطلوب في المصفوفة. في هياكل البيانات الأخرى، مثل القوائم المرتبطة ، تُستخدم المؤشرات كمراجع لربط جزء من الهيكل بجزء آخر بشكل صريح.

تُستخدم المؤشرات لتمرير المعلمات عن طريق المرجع. وهذا مفيد إذا أراد المبرمج أن تكون تعديلات الدالة على معلمة مرئية لمتصل الدالة. وهذا مفيد أيضًا لإرجاع قيم متعددة من دالة.

يمكن أيضًا استخدام المؤشرات لتخصيص وإلغاء تخصيص المتغيرات والمصفوفات الديناميكية في الذاكرة. نظرًا لأن المتغير غالبًا ما يصبح زائدًا عن الحاجة بعد أن يؤدي غرضه، فإن الاحتفاظ به يعد إهدارًا للذاكرة، وبالتالي فإن إلغاء تخصيصه (باستخدام مرجع المؤشر الأصلي) عندما لم تعد هناك حاجة إليه يعد ممارسة جيدة. قد يؤدي الفشل في القيام بذلك إلى تسرب الذاكرة (حيث تقل الذاكرة الحرة المتاحة تدريجيًا، أو في الحالات الشديدة بسرعة، بسبب تراكم العديد من كتل الذاكرة الزائدة).

مؤشرات C

الصيغة الأساسية لتعريف المؤشر هي: [4]

int * ptr ؛ 

يعلن هذا ptrكمعرف لكائن من النوع التالي:

  • مؤشر يشير إلى كائن من النوعint

يتم عادةً التعبير عن ذلك بشكل أكثر إيجازًا على النحو التالي: " ptrهو مؤشر إلى int."

نظرًا لأن لغة C لا تحدد تهيئة ضمنية لكائنات مدة التخزين التلقائية، [5] فيجب توخي الحذر غالبًا للتأكد من أن العنوان الذي ptrيشير إليه صالح؛ وهذا هو السبب في أنه يُقترح أحيانًا تهيئة المؤشر صراحةً إلى قيمة المؤشر الصفرية ، والتي يتم تحديدها تقليديًا في C باستخدام الماكرو القياسي NULL: [6]

int * ptr = NULL ؛   

يؤدي إلغاء الرجوع إلى مؤشر فارغ في لغة C إلى ظهور سلوك غير محدد ، [7] والذي قد يكون كارثيًا. ومع ذلك، فإن معظم التطبيقات [ بحاجة لمصدر ] توقف ببساطة تنفيذ البرنامج المعني، وعادةً ما يكون ذلك بسبب خطأ التجزئة .

ومع ذلك، فإن تهيئة المؤشرات بشكل غير ضروري قد يعيق تحليل البرنامج، وبالتالي إخفاء الأخطاء.

على أية حال، بمجرد إعلان المؤشر، فإن الخطوة المنطقية التالية هي أن يشير إلى شيء ما:

int a = 5 ؛ int * ptr = NULL ؛   
   

نقطة = &a a ؛  

يؤدي هذا إلى تعيين قيمة عنوان aإلى ptr. على سبيل المثال، إذا aتم تخزينه في موقع الذاكرة 0x8130، فستكون قيمة ptr0x8130 بعد التعيين. لإلغاء مرجع المؤشر، يتم استخدام علامة النجمة مرة أخرى:

* نقطة = 8 ؛  

هذا يعني أخذ محتويات ptr(والتي هي 0x8130)، و"تحديد" هذا العنوان في الذاكرة وتعيين قيمته إلى 8. إذا aتم الوصول إليه مرة أخرى لاحقًا، فستكون قيمته الجديدة 8.

قد يكون هذا المثال أكثر وضوحًا إذا تم فحص الذاكرة مباشرةً. افترض أن الجهاز aيقع عند العنوان 0x8130 في الذاكرة ptrوعند 0x8134؛ افترض أيضًا أن هذا جهاز 32 بت بحيث يكون عرض int 32 بت. فيما يلي ما سيكون في الذاكرة بعد تنفيذ مقتطف التعليمات البرمجية التالي:

int a = 5 ؛ int * ptr = NULL ؛   
   
عنوان محتويات
0x8130 0x00000005
0x8134 0x00000000

(مؤشر NULL الموضح هنا هو 0x00000000.) عن طريق تعيين عنوان aإلى ptr:

نقطة = &a a ؛  

يُنتج قيم الذاكرة التالية:

عنوان محتويات
0x8130 0x00000005
0x8134 0x00008130

ثم عن طريق إلغاء الإشارة ptrعن طريق الترميز:

* نقطة = 8 ؛  

سيقوم الكمبيوتر بأخذ محتويات ptr(والتي هي 0x8130)، و"تحديد" هذا العنوان، وتعيين 8 لهذا الموقع مما يؤدي إلى إنتاج الذاكرة التالية:

عنوان محتويات
0x8130 0x00000008
0x8134 0x00008130

من الواضح أن الوصول aسيؤدي إلى الحصول على القيمة 8 لأن التعليمات السابقة عدلت محتويات aعن طريق المؤشر ptr.

الاستخدام في هياكل البيانات

عند إعداد هياكل البيانات مثل القوائم والطوابير والأشجار، من الضروري وجود مؤشرات للمساعدة في إدارة كيفية تنفيذ الهيكل والتحكم فيه. ومن الأمثلة النموذجية للمؤشرات مؤشرات البداية ومؤشرات النهاية ومؤشرات المكدس . يمكن أن تكون هذه المؤشرات مطلقة ( العنوان الفعلي أو عنوان افتراضي في الذاكرة الافتراضية ) أو نسبية ( إزاحة من عنوان بداية مطلق ("أساسي") يستخدم عادةً عددًا أقل من البتات مقارنة بالعنوان الكامل، ولكنه يتطلب عادةً عملية حسابية إضافية لحلها).

العناوين النسبية هي شكل من أشكال تقسيم الذاكرة اليدوي ، وتشترك في العديد من مزاياها وعيوبها. يمكن استخدام إزاحة مكونة من بايتين، تحتوي على عدد صحيح غير موقّع مكون من 16 بت، لتوفير عنونة نسبية لما يصل إلى 64 كيلوبايت (2 16 بايت) من بنية بيانات. يمكن تمديد ذلك بسهولة إلى 128 أو 256 أو 512 كيلوبايت إذا تم فرض محاذاة العنوان المشار إليه على نصف كلمة أو كلمة أو حد مزدوج الكلمة (ولكن، يتطلب عملية "تحويل إلى اليسار" إضافية - بمقدار 1 أو 2 أو 3 بتات - من أجل ضبط الإزاحة بعامل 2 أو 4 أو 8، قبل إضافتها إلى العنوان الأساسي). ومع ذلك، بشكل عام، فإن مثل هذه المخططات تسبب الكثير من المتاعب، ولتسهيل الأمر على المبرمج، يفضل العناوين المطلقة (والأساسية لذلك، مساحة عنوان مسطحة ).

يمكن استخدام إزاحة بايت واحد، مثل قيمة ASCII السداسية العشرية لحرف (مثل X'29') للإشارة إلى قيمة عددية بديلة (أو فهرس) في مصفوفة (مثل X'01'). بهذه الطريقة، يمكن ترجمة الأحرف بكفاءة عالية من " البيانات الخام " إلى فهرس متسلسل قابل للاستخدام ثم إلى عنوان مطلق بدون جدول بحث .

مصفوفات سي

في لغة C، يتم تعريف فهرسة المصفوفة رسميًا من حيث حساب المؤشر؛ أي أن مواصفات اللغة تتطلب أن array[i]تكون مكافئة لـ *(array + i). [8] وبالتالي، في لغة C، يمكن التفكير في المصفوفات كمؤشرات لمناطق متتالية من الذاكرة (بدون فجوات)، [8] والتركيب النحوي للوصول إلى المصفوفات متطابق مع التركيب النحوي الذي يمكن استخدامه لإلغاء مرجع المؤشرات. على سبيل المثال، يمكن إعلان المصفوفة arrayواستخدامها بالطريقة التالية:

int array [ 5 ]; /* يعلن عن 5 أعداد صحيحة متجاورة */ int * ptr = array ; /* يمكن استخدام المصفوفات كمؤشرات */ ptr [ 0 ] = 1 ; /* يمكن فهرسة المؤشرات باستخدام صيغة المصفوفة */ * ( array + 1 ) = 2 ; /* يمكن إلغاء مرجع المصفوفات باستخدام صيغة المؤشر */ * ( 1 + array ) = 2 ; /* إضافة المؤشر عملية تبديلية */ 2 [ array ] = 4 ; /* عامل الخفض عملية تبديلية */       
     
          
      
      
        

يقوم هذا بتخصيص كتلة من خمسة أعداد صحيحة ويطلق على الكتلة اسم array، والتي تعمل كمؤشر للكتلة. استخدام شائع آخر للمؤشرات هو الإشارة إلى الذاكرة المخصصة ديناميكيًا من malloc والتي تعيد كتلة متتالية من الذاكرة لا تقل عن الحجم المطلوب والتي يمكن استخدامها كمصفوفة.

في حين أن معظم المشغلات على المصفوفات والمؤشرات متكافئة، فإن نتيجة sizeofالمشغل تختلف. في هذا المثال، sizeof(array)سيتم تقييم إلى 5*sizeof(int)(حجم المصفوفة)، بينما sizeof(ptr)سيتم تقييم إلى sizeof(int*)، حجم المؤشر نفسه.

يمكن إعلان القيم الافتراضية للمصفوفة مثل:

مصفوفة int [ 5 ] = { 2 ، 4 ، 3 ، 1 ، 5        

إذا كان موجودًا في الذاكرة بدءًا من العنوان 0x1000 على جهاز Little-endianarray 32 بت، فستحتوي الذاكرة على ما يلي (القيم بالنظام السداسي عشر ، مثل العناوين):

0 1 2 3
1000 2 0 0 0
1004 4 0 0 0
1008 3 0 0 0
100 درجة مئوية 1 0 0 0
1010 5 0 0 0

يتم تمثيل خمسة أعداد صحيحة هنا: 2 و4 و3 و1 و5. تشغل هذه الأعداد الصحيحة الخمسة 32 بت (4 بايت) كل منها مع تخزين البايت الأقل أهمية أولاً (وهذا هو بنية وحدة المعالجة المركزية ذات الطرف الصغير ) ويتم تخزينها على التوالي بدءًا من العنوان 0x1000.

الصيغة المستخدمة في لغة C مع المؤشرات هي:

  • arrayيعني 0x1000؛
  • array + 1يعني 0x1004: "+ 1" يعني إضافة حجم 1 int، وهو 4 بايت؛
  • *arrayيعني إلغاء مرجع محتويات array. مع اعتبار المحتويات كعنوان ذاكرة (0x1000)، ابحث عن القيمة في هذا الموقع (0x0002)؛
  • array[i]يعني رقم العنصر i، على أساس 0، arrayوالذي يتم ترجمته إلى *(array + i).

المثال الأخير هو كيفية الوصول إلى محتويات array. وتفصيل ذلك:

  • array + iهو موقع الذاكرة للعنصر (i) من ، arrayبدءًا من i=0؛
  • *(array + i)يأخذ عنوان الذاكرة هذا ويزيل مرجعيته للوصول إلى القيمة.

قائمة مرتبطة بـ C

فيما يلي مثال لتعريف القائمة المرتبطة في لغة C.

/* يتم تمثيل القائمة المرتبطة الفارغة بـ NULL 
* أو بعض القيم الحارسة الأخرى */ 
#define EMPTY_LIST NULL

struct link { void * data ; /* بيانات هذا الرابط */ struct link * next ; /* الرابط التالي؛ قائمة فارغة إذا لم يكن هناك أي قائمة */ };  
              
        

هذا التعريف التكراري للمؤشر هو في الأساس نفس التعريف التكراري المرجعي من لغة برمجة Haskell :

 رابط البيانات أ = لا شيء | سلبيات أ ( رابط أ )    
                 

Nilهي القائمة الفارغة، وهي Cons a (Link a)خلية cons من النوع aمع رابط آخر أيضًا من النوع a.

ومع ذلك، يتم التحقق من نوع التعريف مع المراجع ولا يستخدم قيم إشارة مربكة محتملة. لهذا السبب، يتم التعامل مع هياكل البيانات في C عادةً عبر وظائف التغليف ، والتي يتم فحصها بعناية للتأكد من صحتها.

تمرير العنوان باستخدام المؤشرات

يمكن استخدام المؤشرات لتمرير المتغيرات حسب عناوينها، مما يسمح بتغيير قيمتها. على سبيل المثال، ضع في اعتبارك الكود C التالي :

/* يمكن تغيير نسخة من int n داخل الوظيفة دون التأثير على كود الاستدعاء */ 
void passByValue ( int n ) { n = 12 ; }   
      


/* يتم تمرير المؤشر m بدلاً من ذلك. لا يتم إنشاء نسخة من القيمة التي يشير إليها m */ 
void passByAddress ( int * m ) { * m = 14 ; }   
      


int main ( void ) { int x = 3 ؛  
       

    /* قم بتمرير نسخة من قيمة x كحجة */ 
passByValue ( x ); // تم تغيير القيمة داخل الدالة، ولكن x لا تزال 3 من هنا فصاعدًا    
    

    /* قم بتمرير عنوان x كحجة */ 
passByAddress ( & x ); // تم تغيير x بالفعل بواسطة الوظيفة وهو الآن يساوي 14 هنا    
    

    العودة 0 ؛ } 

تخصيص الذاكرة الديناميكية

في بعض البرامج، تعتمد الكمية المطلوبة من الذاكرة على ما قد يدخله المستخدم . في مثل هذه الحالات، يحتاج المبرمج إلى تخصيص الذاكرة بشكل ديناميكي. يتم ذلك عن طريق تخصيص الذاكرة في الكومة بدلاً من المكدس ، حيث يتم تخزين المتغيرات عادةً (على الرغم من أنه يمكن أيضًا تخزين المتغيرات في سجلات وحدة المعالجة المركزية). لا يمكن إجراء تخصيص الذاكرة الديناميكي إلا من خلال المؤشرات، ولا يمكن إعطاء الأسماء - كما هو الحال مع المتغيرات الشائعة.

تُستخدم المؤشرات لتخزين وإدارة عناوين كتل الذاكرة المخصصة ديناميكيًا . تُستخدم هذه الكتل لتخزين كائنات البيانات أو مجموعات الكائنات. توفر معظم اللغات المنظمة والموجهة للكائنات مساحة من الذاكرة، تسمى الكومة أو المخزن الحر ، والتي يتم تخصيص الكائنات منها ديناميكيًا.

يوضح مثال الكود C أدناه كيفية تخصيص كائنات البنية والإشارة إليها ديناميكيًا. توفر مكتبة C القياسية الوظيفة malloc()لتخصيص كتل الذاكرة من الكومة. تأخذ حجم الكائن المراد تخصيصه كمعلمة وتعيد مؤشرًا إلى كتلة ذاكرة مخصصة حديثًا مناسبة لتخزين الكائن، أو تعيد مؤشرًا فارغًا إذا فشل التخصيص.

/* عنصر مخزون الأجزاء */ 
struct Item { int id ; /* رقم الجزء */ char * name ; /* اسم الجزء */ float cost ; /* التكلفة */ };  
                  
              
              


/* تخصيص وتهيئة كائن عنصر جديد */ 
struct Item * make_item ( const char * name ) { struct Item * item ;      
       

    /* تخصيص كتلة من الذاكرة لكائن عنصر جديد */ 
item = malloc ( sizeof ( struct Item )); if ( item == NULL ) return NULL ;       
       
         

    /* تهيئة أعضاء العنصر الجديد */ 
memset ( item , 0 , sizeof ( struct Item )); item -> id = -1 ; item -> name = NULL ; item -> cost = 0.0 ;       
        
      
      

    /* احفظ نسخة من الاسم في العنصر الجديد */ 
item -> name = malloc ( strlen ( name ) + 1 ); if ( item -> name == NULL ) { free ( item ); return NULL ; } strcpy ( item -> name , name );        
        
        
         
    
     

    
/ * إرجاع كائن العنصر الذي تم إنشاؤه حديثًا */ return item ;     

يوضح الكود أدناه كيفية إلغاء تخصيص كائنات الذاكرة ديناميكيًا، أي إعادتها إلى الكومة أو المخزن الحر. توفر مكتبة C القياسية الوظيفة free()لإلغاء تخصيص كتلة ذاكرة تم تخصيصها مسبقًا وإعادتها إلى الكومة.

/* إلغاء تخصيص كائن عنصر */ 
void destroy_item ( struct Item * item ) { /* التحقق من وجود مؤشر كائن فارغ */ if ( item == NULL ) return ;    
    
       
        

    /* إلغاء تخصيص سلسلة الاسم المحفوظة داخل العنصر */ 
if ( item -> name != NULL ) { free ( item -> name ); item -> name = NULL ; }        
        
          
    

    /* إلغاء تخصيص كائن العنصر نفسه */ 
free ( item ); }    

الأجهزة المخصصة للذاكرة

في بعض بنيات الحوسبة، يمكن استخدام المؤشرات للتعامل بشكل مباشر مع الذاكرة أو الأجهزة المخصصة للذاكرة.

يعد تعيين العناوين للمؤشرات أداة لا تقدر بثمن عند برمجة المتحكمات الدقيقة . فيما يلي مثال بسيط لإعلان مؤشر من نوع int وتهيئته إلى عنوان سداسي عشري في هذا المثال الثابت 0x7FFF:

int * عنوان الأجهزة = ( int * ) 0x7FFF ؛    

في منتصف الثمانينيات، كان استخدام نظام BIOS للوصول إلى إمكانيات الفيديو في أجهزة الكمبيوتر الشخصية بطيئًا. كانت التطبيقات التي كانت تعتمد على العرض المكثف تستخدم عادةً للوصول إلى ذاكرة الفيديو CGA مباشرةً عن طريق إرسال الثابت السداسي عشر 0xB8000 إلى مؤشر إلى مجموعة من 80 قيمة int غير موقعة مكونة من 16 بتًا. تتكون كل قيمة من رمز ASCII في البايت السفلي، ولون في البايت العلوي. وبالتالي، لوضع الحرف "A" في الصف 5، العمود 2 باللون الأبيض الساطع على الأزرق، يجب كتابة رمز مثل التالي:

#define VID ((unsigned short (*)[80])0xB8000)

void foo ( void ) { VID [ 4 ] [ 1 ] = 0x1F00 | "أ" ؛ }  
        

الاستخدام في جداول التحكم

تستخدم جداول التحكم التي تستخدم للتحكم في تدفق البرنامج عادةً مؤشرات بشكل مكثف. يمكن استخدام المؤشرات، المضمنة عادةً في إدخال جدول، على سبيل المثال، للاحتفاظ بنقاط الدخول إلى البرامج الفرعية التي سيتم تنفيذها، استنادًا إلى شروط معينة محددة في نفس إدخال الجدول. ومع ذلك، يمكن أن تكون المؤشرات ببساطة فهرسًا لجداول أخرى منفصلة، ​​ولكن مرتبطة، تتألف من مجموعة من العناوين الفعلية أو العناوين نفسها (اعتمادًا على هياكل لغة البرمجة المتاحة). يمكن أيضًا استخدامها للإشارة إلى إدخالات الجدول السابقة (كما في معالجة الحلقة) أو التوجيه إلى الأمام لتخطي بعض إدخالات الجدول (كما في التبديل أو الخروج "المبكر" من الحلقة). لهذا الغرض الأخير، قد يكون "المؤشر" ببساطة رقم إدخال الجدول نفسه ويمكن تحويله إلى عنوان فعلي من خلال الحساب البسيط.

المؤشرات المكتوبة والتحويل

في العديد من اللغات، تحتوي المؤشرات على قيد إضافي يتمثل في أن الكائن الذي تشير إليه له نوع معين . على سبيل المثال، قد يتم إعلان مؤشر للإشارة إلى عدد صحيح ؛ ستحاول اللغة بعد ذلك منع المبرمج من توجيهه إلى كائنات ليست أعدادًا صحيحة، مثل الأرقام ذات الفاصلة العائمة ، مما يؤدي إلى التخلص من بعض الأخطاء.

على سبيل المثال، في لغة C

int * المال ؛ char * الحقائب ؛ 
 

moneyسيكون مؤشرًا صحيحًا وسيكون bagsمؤشرًا حرفيًا. سيؤدي ما يلي إلى ظهور تحذير للمترجم بشأن "التعيين من نوع مؤشر غير متوافق" ضمن GCC

الحقائب = المال ؛  

لأن moneyو bagsتم إعلانهما بأنواع مختلفة. لقمع تحذير المترجم، يجب توضيح أنك ترغب بالفعل في إجراء التعيين عن طريق تحويله إلى نوع آخر

الأكياس = ( char * ) المال ؛   

الذي يقول بتحويل مؤشر عدد صحيح moneyإلى مؤشر char وتعيينه إلى bags.

تتطلب مسودة عام 2005 لمعيار C أن تحويل مؤشر مشتق من نوع إلى مؤشر من نوع آخر يجب أن يحافظ على صحة المحاذاة لكلا النوعين (6.3.2.3 المؤشرات، الفقرة 7): [9]

char * external_buffer = "abcdef" ; int * internal_data ;   
 

internal_data = ( int * ) external_buffer ؛ // سلوك غير محدد إذا " لم يتم محاذاة المؤشر الناتج بشكل صحيح"     
                                         

في اللغات التي تسمح بالحسابات المؤشرية، تأخذ الحسابات على المؤشرات في الاعتبار حجم النوع. على سبيل المثال، يؤدي إضافة رقم صحيح إلى مؤشر إلى إنتاج مؤشر آخر يشير إلى عنوان أعلى بمقدار هذا الرقم مضروبًا في حجم النوع. يتيح لنا هذا حساب عنوان عناصر مصفوفة من نوع معين بسهولة، كما هو موضح في مثال مصفوفات C أعلاه. عندما يتم تحويل مؤشر من نوع ما إلى نوع آخر بحجم مختلف، يجب أن يتوقع المبرمج أن حساب المؤشر سيتم بشكل مختلف. في C، على سبيل المثال، إذا moneyبدأت المصفوفة عند 0x2000 sizeof(int)وكانت 4 بايت بينما sizeof(char)كانت 1 بايت، فسوف money + 1تشير إلى 0x2004، لكنها bags + 1ستشير إلى 0x2001. تشمل المخاطر الأخرى للتحويل فقدان البيانات عند كتابة بيانات "واسعة" في مواقع "ضيقة" (على سبيل المثال bags[0] = 65537;)، ونتائج غير متوقعة عند تحويل القيم بالبت ، ومشاكل المقارنة، خاصة مع القيم الموقعة وغير الموقعة.

على الرغم من أنه من المستحيل بشكل عام تحديد التحويلات الآمنة في وقت التجميع، فإن بعض اللغات تخزن معلومات النوع في وقت التشغيل والتي يمكن استخدامها لتأكيد أن هذه التحويلات الخطيرة صالحة في وقت التشغيل. تقبل لغات أخرى تقريبًا متحفظًا للتحويلات الآمنة، أو لا تقبل أيًا منها على الإطلاق.

قيمة المؤشرات

في لغة C وC++، حتى إذا تمت مقارنة مؤشرين على أنهما متساويان، فهذا لا يعني أنهما متكافئان. في هذه اللغات و LLVM ، يتم تفسير القاعدة على أنها تعني أن "مجرد أن يشير مؤشران إلى نفس العنوان، لا يعني أنهما متساويان بمعنى أنه يمكن استخدامهما بالتبادل"، يُشار إلى الفرق بين المؤشرات باسم مصدرهما . [ 10] لا يوفر التحويل إلى نوع عدد صحيح مثل uintptr_tالمحدد في التنفيذ والمقارنة التي يوفرها أي نظرة ثاقبة حول ما إذا كان المؤشران قابلين للتبادل. بالإضافة إلى ذلك، فإن التحويل الإضافي إلى البايتات والحسابات من شأنه أن يربك المحسنين الذين يحاولون تتبع استخدام المؤشرات، وهي مشكلة لا تزال قيد التوضيح في الأبحاث الأكاديمية. [11]

جعل المؤشرات أكثر أمانًا

نظرًا لأن المؤشر يسمح للبرنامج بمحاولة الوصول إلى كائن قد لا يكون محددًا، فقد تكون المؤشرات مصدرًا لمجموعة متنوعة من أخطاء البرمجة . ومع ذلك، فإن فائدة المؤشرات كبيرة جدًا لدرجة أنه قد يكون من الصعب تنفيذ مهام البرمجة بدونها. وبالتالي، أنشأت العديد من اللغات هياكل مصممة لتوفير بعض الميزات المفيدة للمؤشرات دون بعض عيوبها ، والتي يشار إليها أحيانًا أيضًا باسم مخاطر المؤشر . في هذا السياق، يشار إلى المؤشرات التي تخاطب الذاكرة مباشرة (كما تستخدم في هذه المقالة) باسمالمؤشرات الخام ، على النقيض منالمؤشرات الذكيةأو المتغيرات الأخرى.

تتمثل إحدى المشكلات الرئيسية المتعلقة بالمؤشرات في أنه طالما يمكن التعامل معها مباشرة كرقم، فيمكن جعلها تشير إلى عناوين غير مستخدمة أو إلى بيانات يتم استخدامها لأغراض أخرى. تستبدل العديد من اللغات، بما في ذلك معظم لغات البرمجة الوظيفية ولغات الأمر الحديثة مثل Java ، المؤشرات بنوع أكثر غموضًا من المرجع، يشار إليه عادةً باسم مرجع بسيط ، والذي لا يمكن استخدامه إلا للإشارة إلى الكائنات ولا يتم التعامل معه كأرقام، مما يمنع هذا النوع من الخطأ. تتم معالجة فهرسة المصفوفة كحالة خاصة.

يُطلق على المؤشر الذي لا يحتوي على أي عنوان مُعين له اسم المؤشر البري . قد تتسبب أي محاولة لاستخدام مثل هذه المؤشرات غير المهيئة في حدوث سلوك غير متوقع، إما لأن القيمة الأولية ليست عنوانًا صالحًا، أو لأن استخدامها قد يؤدي إلى إتلاف أجزاء أخرى من البرنامج. غالبًا ما تكون النتيجة خطأ في التجزئة أو انتهاكًا للتخزين أو فرعًا بريًا (إذا تم استخدامه كمؤشر وظيفة أو عنوان فرع).

في الأنظمة التي تحتوي على تخصيص واضح للذاكرة، من الممكن إنشاء مؤشر معلق عن طريق إلغاء تخصيص منطقة الذاكرة التي يشير إليها. هذا النوع من المؤشرات خطير وخفي لأن منطقة الذاكرة التي تم إلغاء تخصيصها قد تحتوي على نفس البيانات التي كانت تحتوي عليها قبل إلغاء تخصيصها ولكن قد يتم إعادة تخصيصها واستبدالها بكود غير ذي صلة وغير معروف للكود السابق. تمنع اللغات التي تحتوي على جمع القمامة هذا النوع من الأخطاء لأن إلغاء التخصيص يتم تلقائيًا عندما لا توجد مراجع أخرى في النطاق.

تدعم بعض اللغات، مثل C++ ، المؤشرات الذكية ، والتي تستخدم شكلًا بسيطًا من العد المرجعي للمساعدة في تتبع تخصيص الذاكرة الديناميكية بالإضافة إلى العمل كمرجع. في حالة عدم وجود دورات مرجعية، حيث يشير الكائن إلى نفسه بشكل غير مباشر من خلال سلسلة من المؤشرات الذكية، فإن هذا يزيل احتمالية وجود مؤشرات معلقة وتسربات الذاكرة. تدعم سلاسل Delphi العد المرجعي بشكل أصلي.

تقدم لغة برمجة Rust أداة فحص الاقتراض ، وعمر المؤشرات ، وتحسينًا يعتمد على أنواع الخيارات للمؤشرات الفارغة للتخلص من أخطاء المؤشر، دون اللجوء إلى جمع القمامة .

أنواع خاصة من المؤشرات

الأنواع المحددة بالقيمة

مؤشر فارغ

يحتوي المؤشر الفارغ على قيمة محجوزة للإشارة إلى أن المؤشر لا يشير إلى كائن صالح. تُستخدم المؤشرات الفارغ بشكل روتيني لتمثيل الحالات مثل نهاية قائمة بطول غير معروف أو الفشل في تنفيذ بعض الإجراءات؛ ويمكن مقارنة هذا الاستخدام للمؤشرات الفارغ بأنواع قابلة للعدم وقيمة Nothing في نوع الخيار .

مؤشر معلق

المؤشر المعلق هو مؤشر لا يشير إلى كائن صالح وبالتالي قد يتسبب في تعطل البرنامج أو التصرف بشكل غريب. في لغات البرمجة باسكال أو سي ، قد تشير المؤشرات التي لم يتم تهيئتها بشكل خاص إلى عناوين غير متوقعة في الذاكرة.

يُظهر الكود المثال التالي مؤشرًا معلقًا:

int func ( void ) { char * p1 = malloc ( sizeof ( char )); /* (undefined) value of some place on the heap */ char * p2 ; /* dangling (unitialized) pointer */ * p1 = 'a' ; /* هذا جيد، على افتراض أن malloc() لم يرجع NULL. */ * p2 = 'b' ; /* هذا يستدعي سلوكًا غير محدد */ }  
        
            
            
            

هنا، p2قد يشير إلى أي مكان في الذاكرة، لذا فإن تنفيذ المهمة *p2 = 'b';قد يؤدي إلى إتلاف منطقة غير معروفة من الذاكرة أو تشغيل خطأ التجزئة .

فرع بري

عندما يتم استخدام مؤشر كعنوان لنقطة الدخول إلى برنامج أو بداية لوظيفة لا تعيد أي شيء وهي أيضًا غير مهيأة أو تالفة، فإذا تم إجراء استدعاء أو انتقال إلى هذا العنوان، يقال إن " فرعًا بريًا " قد حدث. بعبارة أخرى، الفرع البري هو مؤشر وظيفة بري (متدلٍ).

إن العواقب عادة ما تكون غير متوقعة وقد يظهر الخطأ بعدة طرق مختلفة اعتمادًا على ما إذا كان المؤشر عنوانًا "صالحًا" أم لا وما إذا كان هناك (مصادفة) تعليمة صالحة (كود تشغيلي) في هذا العنوان أم لا. إن اكتشاف فرع بري يمكن أن يمثل أحد أصعب تمارين التصحيح وأكثرها إحباطًا نظرًا لأن الكثير من الأدلة قد تم تدميرها مسبقًا أو من خلال تنفيذ تعليمة أو أكثر غير مناسبة في موقع الفرع. إذا كان متاحًا، فإن محاكي مجموعة التعليمات يمكنه عادةً ليس فقط اكتشاف فرع بري قبل أن يسري مفعوله، بل وأيضًا توفير تتبع كامل أو جزئي لتاريخه.

الأنواع المحددة حسب البنية

مؤشر نسبي تلقائي

المؤشر النسبي التلقائي هو مؤشر يتم تفسير قيمته كإزاحة من عنوان المؤشر نفسه؛ وبالتالي، إذا كان هيكل البيانات يحتوي على عضو مؤشر نسبي تلقائي يشير إلى جزء من هيكل البيانات نفسه، فيمكن نقل هيكل البيانات في الذاكرة دون الحاجة إلى تحديث قيمة المؤشر النسبي التلقائي. [12]

تستخدم براءة الاختراع المذكورة أيضًا مصطلح المؤشر النسبي الذاتي ليعني نفس الشيء. ومع ذلك، فقد تم استخدام معنى هذا المصطلح بطرق أخرى:

  • أن يعني إزاحة من عنوان الهيكل وليس من عنوان المؤشر نفسه؛ [ بحاجة لمصدر ]
  • أن يعني مؤشرًا يحتوي على عنوانه الخاص، والذي يمكن أن يكون مفيدًا لإعادة بناء مجموعة من هياكل البيانات التي تشير إلى بعضها البعض في أي منطقة عشوائية من الذاكرة. [13]

مؤشر قائم على

المؤشر الأساسي هو مؤشر تكون قيمته إزاحة عن قيمة مؤشر آخر. ويمكن استخدامه لتخزين وتحميل كتل البيانات، وتعيين عنوان بداية الكتلة للمؤشر الأساسي. [14]

الأنواع المحددة حسب الاستخدام أو نوع البيانات

توجيهات متعددة

في بعض اللغات، يمكن لمؤشر أن يشير إلى مؤشر آخر، مما يتطلب عمليات إلغاء مرجعية متعددة للوصول إلى القيمة الأصلية. وبينما قد يضيف كل مستوى من مستويات الإحالة غير المباشرة تكلفة أداء، إلا أنه ضروري في بعض الأحيان لتوفير سلوك صحيح لهياكل البيانات المعقدة . على سبيل المثال، في لغة C، من المعتاد تعريف قائمة مرتبطة من حيث عنصر يحتوي على مؤشر إلى العنصر التالي في القائمة:

عنصر البنية { عنصر البنية * التالي ؛ قيمة int ؛ };  
      
                


عنصر البنية * الرأس = NULL ؛    

يستخدم هذا التنفيذ مؤشرًا إلى العنصر الأول في القائمة كبديل للقائمة بأكملها. إذا تمت إضافة قيمة جديدة إلى بداية القائمة، headفيجب تغييرها للإشارة إلى العنصر الجديد. نظرًا لأن وسيطات C يتم تمريرها دائمًا بالقيمة، فإن استخدام الإحالة المزدوجة يسمح بتنفيذ الإدراج بشكل صحيح، وله التأثير الجانبي المرغوب فيه المتمثل في التخلص من كود الحالة الخاصة للتعامل مع عمليات الإدراج في مقدمة القائمة:

// بالنظر إلى القائمة المفرزة في *head، أدخل عنصر العنصر في أول 
موقع حيث تكون قيمة جميع العناصر السابقة أقل أو مساوية. 
void insert ( struct element ** head , struct element * item ) { struct element ** p ; // يشير p إلى مؤشر إلى عنصر for ( p = head ; * p != NULL ; p = & ( * p ) -> next ) { if ( item -> value <= ( * p ) -> value ) break ; } item -> next = * p ; * p = item ; }       
        
              
           
            
    
      
      


// يقوم المتصل بما يلي: 
insert ( & head , item ); 

في هذه الحالة، إذا كانت قيمة itemأقل من قيمة head، فسيتم تحديث المتصل headبشكل صحيح إلى عنوان العنصر الجديد.

يوجد مثال أساسي في وسيطة argv للوظيفة الرئيسية في C (وC++) ، والتي تم تقديمها في النموذج الأولي على النحو التالي char **argv— وذلك لأن المتغير argvنفسه هو مؤشر إلى مجموعة من السلاسل (مجموعة من المصفوفات)، وبالتالي *argvفهو مؤشر إلى السلسلة رقم 0 (حسب الاتفاقية اسم البرنامج)، وهو **argvالحرف رقم 0 من السلسلة رقم 0.

مؤشر الوظيفة

في بعض اللغات، يمكن للمؤشر أن يشير إلى كود قابل للتنفيذ، أي أنه يمكن أن يشير إلى دالة أو طريقة أو إجراء. سيخزن مؤشر الدالة عنوان الدالة التي سيتم استدعاؤها. وبينما يمكن استخدام هذه الميزة لاستدعاء الدوال بشكل ديناميكي، إلا أنها غالبًا ما تكون تقنية مفضلة لدى كتاب الفيروسات والبرامج الضارة الأخرى.

int sum ( int n1 ، int n2 ) { // دالة تحتوي على معاملين صحيحين ترجع قيمة صحيحة return n1 + n2 ؛ }        
       


int main ( void ) { int a , b , x , y ; int ( * fp )( int , int ); // مؤشر دالة يمكنه الإشارة إلى دالة مثل sum fp = & sum ; // يشير fp الآن إلى الدالة sum x = ( * fp )( a , b ); // يستدعي الدالة sum بالوسيطات a و b y = sum ( a , b ); // يستدعي الدالة sum بالوسيطات a و b }  
        
          
                    
               
                 

مؤشر الرجوع

في القوائم المرتبطة بشكل مزدوج أو هياكل الشجرة ، يشير المؤشر الخلفي الموجود على عنصر إلى العنصر الذي يشير إلى العنصر الحالي. وهذا مفيد للتنقل والتلاعب، على حساب استخدام ذاكرة أكبر.

المحاكاة باستخدام مؤشر المصفوفة

من الممكن محاكاة سلوك المؤشر باستخدام فهرس لمصفوفة (أحادية البعد عادةً).

في المقام الأول بالنسبة للغات التي لا تدعم المؤشرات صراحةً ولكنها تدعم المصفوفات، يمكن التفكير في المصفوفة ومعالجتها كما لو كانت نطاق الذاكرة بالكامل (في نطاق المصفوفة المعينة) ويمكن التفكير في أي فهرس لها على أنه معادل لسجل عام في لغة التجميع (يشير إلى البايتات الفردية ولكن قيمته الفعلية نسبية لبداية المصفوفة، وليس عنوانها المطلق في الذاكرة). بافتراض أن المصفوفة هي، على سبيل المثال، بنية بيانات متجاورة بحجم 16 ميغا بايت ، يمكن معالجة البايتات الفردية (أو سلسلة من البايتات المتجاورة داخل المصفوفة) والتلاعب بها مباشرةً باستخدام اسم المصفوفة مع عدد صحيح غير موقّع مكون من 31 بت كمؤشر مُحاكي (هذا مشابه تمامًا لمثال مصفوفات C الموضح أعلاه). يمكن محاكاة حساب المؤشر عن طريق الإضافة أو الطرح من الفهرس، مع الحد الأدنى من النفقات العامة الإضافية مقارنة بحساب المؤشر الحقيقي.

من الممكن نظريًا، باستخدام التقنية المذكورة أعلاه، جنبًا إلى جنب مع محاكي مجموعة التعليمات المناسب ، محاكاة أي كود آلي أو الوسيط ( الكود الثنائي ) لأي معالج/لغة بلغة أخرى لا تدعم المؤشرات على الإطلاق (على سبيل المثال Java / JavaScript ). لتحقيق ذلك، يمكن تحميل الكود الثنائي في البداية إلى بايتات متجاورة من المصفوفة حتى يتمكن المحاكي من "قراءته" وتفسيره والعمل به بالكامل داخل الذاكرة الموجودة في نفس المصفوفة. إذا لزم الأمر، لتجنب مشاكل تجاوز سعة المخزن المؤقت تمامًا ، يمكن عادةً إجراء فحص الحدود للمترجم (أو إذا لم يكن كذلك، يتم ترميزه يدويًا في المحاكي).

دعم في لغات البرمجة المختلفة

آدا

Ada هي لغة كتابة قوية حيث يتم كتابة جميع المؤشرات ولا يُسمح إلا بتحويلات النوع الآمنة. يتم تهيئة جميع المؤشرات افتراضيًا إلى null، وأي محاولة للوصول إلى البيانات من خلال nullمؤشر تتسبب في إثارة استثناء . تسمى المؤشرات في Ada أنواع الوصول . لم تسمح Ada 83 بالحسابات على أنواع الوصول (على الرغم من أن العديد من بائعي المترجمين قدموها كميزة غير قياسية)، لكن Ada 95 تدعم الحساب "الآمن" على أنواع الوصول عبر الحزمة System.Storage_Elements.

أساسي

كانت العديد من الإصدارات القديمة من لغة BASIC لمنصة Windows تدعم الدالة STRPTR() لإرجاع عنوان سلسلة، والدالة VARPTR() لإرجاع عنوان متغير. كما كان يدعم Visual Basic 5 الدالة OBJPTR() لإرجاع عنوان واجهة كائن، والعامل ADDRESSOF لإرجاع عنوان دالة. أنواع كل هذه هي أعداد صحيحة، لكن قيمها تعادل القيم الموجودة في أنواع المؤشرات.

ومع ذلك، فإن اللهجات الأحدث من لغة BASIC ، مثل FreeBASIC أو BlitzMax ، لديها تنفيذات شاملة للمؤشرات. في FreeBASIC، يتم التعامل مع العمليات الحسابية على ANYالمؤشرات (المكافئة للغة C ) كما لو كان المؤشر عبارة عن عرض بايت. لا يمكن إلغاء مرجع المؤشرات، كما هو الحال في C. أيضًا، لن يؤدي التحويل بين مؤشرات أي نوع آخر إلى توليد أي تحذيرات. void*ANYANYANY

dim كعدد صحيح f = 257 dim كأي ptr g = @ f dim كعدد صحيح ptr i = g assert ( * i = 257 ) assert ( ( g + 4 ) = ( @ f + 1 ) )     
      
      
  
        

سي و سي++

في لغة C و C++، المؤشرات هي متغيرات تخزن العناوين ويمكن أن تكون فارغة . كل مؤشر له نوع يشير إليه، ولكن يمكن للمرء أن يقوم بالتحويل بحرية بين أنواع المؤشرات (ولكن ليس بين مؤشر دالة ومؤشر كائن). يسمح نوع مؤشر خاص يسمى "مؤشر فارغ" بالإشارة إلى أي كائن (غير دالة)، ولكنه مقيد بحقيقة أنه لا يمكن إلغاء الرجوع إليه مباشرة (يجب تحويله). غالبًا ما يمكن التلاعب بالعنوان نفسه مباشرةً عن طريق تحويل مؤشر من وإلى نوع صحيح بحجم كافٍ، على الرغم من أن النتائج محددة بواسطة التنفيذ وقد تتسبب بالفعل في سلوك غير محدد؛ في حين أن معايير C السابقة لم يكن بها نوع صحيح مضمون أن يكون كبيرًا بما يكفي، تحدد C99 اسم uintptr_t typedef المحدد في <stdint.h>، ولكن لا يلزم أن يوفره التنفيذ.

يدعم C++ بشكل كامل مؤشرات C وتحويل النوع في C. كما يدعم مجموعة جديدة من مشغلات تحويل النوع للمساعدة في اكتشاف بعض التحويلات الخطيرة غير المقصودة في وقت التجميع. منذ C++11 ، توفر مكتبة C++ القياسية أيضًا مؤشرات ذكية ( unique_ptr، shared_ptrو weak_ptr) يمكن استخدامها في بعض المواقف كبديل أكثر أمانًا لمؤشرات C البدائية. يدعم C++ أيضًا شكلًا آخر من أشكال المرجع، مختلفًا تمامًا عن المؤشر، يسمى ببساطة المرجع أو نوع المرجع .

حساب المؤشر ، أي القدرة على تعديل عنوان هدف المؤشر باستخدام العمليات الحسابية (وكذلك مقارنات الحجم)، مقيد بمعيار اللغة للبقاء ضمن حدود كائن مصفوفة واحد (أو بعده مباشرة)، وإلا فإنه سيستدعي سلوكًا غير محدد . يؤدي إضافة أو طرح مؤشر إلى تحريكه بمضاعف لحجم نوع البيانات الخاص به . على سبيل المثال، سيؤدي إضافة 1 إلى مؤشر إلى قيم عدد صحيح مكون من 4 بايت إلى زيادة عنوان البايت الذي يشير إليه المؤشر بمقدار 4. يؤدي هذا إلى زيادة المؤشر ليشير إلى العنصر التالي في مصفوفة متجاورة من الأعداد الصحيحة - والتي غالبًا ما تكون النتيجة المقصودة. لا يمكن إجراء حساب المؤشر على voidالمؤشرات لأن نوع void ليس له حجم، وبالتالي لا يمكن إضافة العنوان المشار إليه، على الرغم من أن gcc والمُجمِّعين الآخرين سيقومون بإجراء حساب البايت على void*باعتباره امتدادًا غير قياسي، ويعاملونه كما لو كان char *.

توفر حسابات المؤشر للمبرمج طريقة واحدة للتعامل مع أنواع مختلفة: إضافة وطرح عدد العناصر المطلوبة بدلاً من الإزاحة الفعلية بالبايتات. ( char *تستخدم حسابات المؤشر مع المؤشرات إزاحات البايتات، لأن sizeof(char)تساوي 1 حسب التعريف.) على وجه الخصوص، يعلن تعريف C صراحةً أن بناء الجملة a[n]، وهو nالعنصر -th من المصفوفة a، يعادل *(a + n)، وهو محتوى العنصر الذي يشير إليه a + n. وهذا يعني أن n[a]يعادل a[n]، ويمكن للمرء أن يكتب، على سبيل المثال، a[3]أو 3[a]بشكل جيد بنفس القدر للوصول إلى العنصر الرابع من المصفوفة a.

على الرغم من قوة الحساب بالمؤشر، إلا أنه قد يكون مصدرًا لأخطاء الكمبيوتر . فهو يميل إلى إرباك المبرمجين المبتدئين ، وإجبارهم على سياقات مختلفة: يمكن أن يكون التعبير حسابيًا عاديًا أو حسابيًا بالمؤشر، وفي بعض الأحيان يكون من السهل الخلط بين أحدهما والآخر. واستجابةً لذلك، لا تسمح العديد من لغات الكمبيوتر الحديثة عالية المستوى (على سبيل المثال Java ) بالوصول المباشر إلى الذاكرة باستخدام العناوين. كما تعالج لهجة C الآمنة Cyclone العديد من المشكلات المتعلقة بالمؤشرات. راجع لغة برمجة C لمزيد من المناقشة.

يتم دعم المؤشر أو void،void* في ANSI C وC++ كنوع مؤشر عام. voidيمكن للمؤشر إلى تخزين عنوان أي كائن (وليس دالة)، [a] وفي C، يتم تحويله ضمنيًا إلى أي نوع مؤشر كائن آخر عند التعيين، ولكن يجب تحويله صراحةً إذا تم إلغاء الإشارة إليه. تم استخدام K&R C char*لغرض "المؤشر المستقل عن النوع" (قبل ANSI C).

int x = 4 ؛ void * p1 = & x ؛ int * p2 = p1 ؛ // void* تم تحويله ضمنيًا إلى int*: صالح في لغة C، ولكن ليس في لغة C++ int a = * p2 ؛ int b = * ( int * ) p1 ؛ // عند إلغاء الرجوع إلى السطر المضمّن، لا يوجد تحويل ضمني   
   
          
   
     

لا يسمح C++ بالتحويل الضمني لـ void*إلى أنواع مؤشرات أخرى، حتى في التعيينات. كان هذا قرار تصميم لتجنب عمليات التحويل غير المقصودة وغير المقصودة، على الرغم من أن معظم المترجمين لا يصدرون سوى تحذيرات، وليس أخطاء، عند مواجهة عمليات تحويل أخرى.

int x = 4 ؛ void * p1 = & x ؛ int * p2 = p1 ؛ // هذا يفشل في C++: لا يوجد تحويل ضمني من void* int * p3 = ( int * ) p1 ؛ // تحويل على غرار C int * p4 = reinterpret_cast < int *> ( p1 // تحويل C++   
   
                        
                  
     

في C++، لا يوجد void&(مرجع إلى void) لتكملة void*(مؤشر إلى void)، لأن المراجع تتصرف مثل الأسماء المستعارة للمتغيرات التي تشير إليها، ولا يمكن أن يكون هناك متغير نوعه void.

مؤشر إلى العضو

في لغة C++، يمكن تعريف مؤشرات إلى أعضاء غير ثابتة في فئة ما. إذا كانت الفئة Cتحتوي على عضو T a، فإن هذا العضو &C::aيكون مؤشرًا إلى العضو aمن النوع T C::*. يمكن أن يكون هذا العضو كائنًا أو دالة . [16] ويمكن استخدامها على الجانب الأيمن من المشغلات .*للوصول ->*إلى العضو المقابل.

البنية S { int a ؛ int f () const { return a ؛} }; S s1 {}; S * ptrS = & s1 ؛  
 
    

 
   

int S ::* ptr = & S :: a ; // مؤشر إلى S::a int ( S ::* fp )() const = & S :: f ; // مؤشر إلى S::f     
     

s1 . * ptr = 1 ؛ std :: cout << ( s1 . * fp )() << " \n " ؛ // يطبع 1 ptrS ->* ptr = 2 ؛ std :: cout << ( ptrS ->* fp )() << " \n " ؛ // يطبع 2  
     
  
     

نظرة عامة على بناء جملة إعلان المؤشر

تغطي إعلانات المؤشرات هذه معظم أشكال إعلانات المؤشرات. بالطبع من الممكن أن يكون هناك مؤشرات ثلاثية، لكن المبادئ الأساسية وراء المؤشر الثلاثي موجودة بالفعل في المؤشر المزدوج. التسمية المستخدمة هنا هي ما typeid(type).name()يعادله التعبير لكل من هذه الأنواع عند استخدام g++ أو clang . [17] [18]

char A5_A5_c [ 5 ][ 5 ]; /* مجموعة من مجموعات الأحرف */ char * A5_Pc [ 5 ]; /* مجموعة من المؤشرات إلى الأحرف */ char ** PPc ; /* مؤشر إلى مؤشر إلى char ("مؤشر مزدوج") */ char ( * PA5_c ) [ 5 ]; /* مؤشر إلى مجموعة(ات) من الأحرف */ char * FPcvE (); /* دالة تعيد مؤشرًا إلى حرف(أحرف) */ char ( * PFcvE )(); /* مؤشر إلى دالة تعيد حرفًا */ char ( * FPA5_cvE ())[ 5 ]; /* دالة تعيد مؤشرًا إلى مجموعة من الأحرف */ char ( * A5_PFcvE [ 5 ])(); /* مجموعة من المؤشرات إلى الدوال التي تعيد حرفًا */     
         
             
       
          
        
  
  

الإعلانات التالية التي تتضمن مؤشرات إلى عضو صالحة فقط في C++:

الفئة C ؛ الفئة D ؛ char C ::* M1Cc ؛ /* مؤشر إلى عضو إلى char */ char C ::* A5_M1Cc [ 5 /* مجموعة مؤشرات إلى عضو إلى char */ char * C ::* M1CPc ؛ /* مؤشر إلى عضو إلى مؤشر إلى حرف(أحرف) */ char C ::** PM1Cc ؛ /* مؤشر إلى مؤشر إلى عضو إلى char */ char ( * M1CA5_c ) [ 5 /* مؤشر إلى عضو إلى مجموعة(أحرف) من الأحرف */ char C ::* FM1CcvE ()؛ /* دالة تعيد مؤشر إلى عضو إلى char */ char D ::* C ::* M1CM1Dc ؛ /* مؤشر إلى عضو إلى مؤشر إلى عضو إلى مؤشر إلى حرف (أحرف) */ char C ::* C ::* M1CMS_c ; /* مؤشر إلى عضو إلى مؤشر إلى عضو إلى مؤشر إلى حرف (أحرف) */ char ( C ::* FM1CA5_cvE ())[ 5 ]; /* دالة تعيد مؤشر إلى عضو إلى مجموعة من الأحرف */ char ( C ::* M1CFcvE )() /* دالة مؤشر إلى عضو تعيد حرفًا */ char ( C :: * A5_M1CFcvE [ 5 ])(); /* مجموعة من مؤشرات إلى دوال أعضاء تعيد حرفًا */ 
 
                
          
              
              
           
           
         
         
   
          
   

()و لديهما []أولوية أعلى من *. [19]

سي شارب

في لغة البرمجة C# ، يتم دعم المؤشرات إما عن طريق وضع علامة على كتل التعليمات البرمجية التي تتضمن مؤشرات باستخدام unsafeالكلمة الأساسية، أو عن طريق usingأحكام System.Runtime.CompilerServicesالتجميع للوصول إلى المؤشر. إن بناء الجملة هو نفسه في الأساس كما هو الحال في C++، ويمكن أن يكون العنوان المشار إليه ذاكرة مُدارة أو غير مُدارة . ومع ذلك، يجب إعلان المؤشرات إلى الذاكرة المُدارة (أي مؤشر إلى كائن مُدار) باستخدام fixedالكلمة الأساسية، مما يمنع جامع القمامة من نقل الكائن المُشار إليه كجزء من إدارة الذاكرة أثناء وجود المؤشر في النطاق، وبالتالي الحفاظ على عنوان المؤشر صالحًا.

ومع ذلك، هناك استثناء من هذا يتمثل في استخدام IntPtrالبنية، والتي تعد مكافئًا مُدارًا للذاكرة لـ int*، ولا تتطلب unsafeالكلمة الأساسية ولا CompilerServicesالتجميع. غالبًا ما يتم إرجاع هذا النوع عند استخدام الأساليب من System.Runtime.InteropServices، على سبيل المثال:

// احصل على 16 بايتًا من الذاكرة من ذاكرة العملية غير المُدارة 
IntPtr pointer = System . Runtime . InteropServices . Marshal . AllocHGlobal ( 16 );   

// افعل شيئًا بالذاكرة المخصصة

// تحرير الذاكرة المخصصة 
System . Runtime . InteropServices . Marshal . FreeHGlobal ( pointer );

يتضمن إطار عمل .NET العديد من الفئات والطرق في مساحات الأسماء Systemو System.Runtime.InteropServices(مثل Marshalالفئة) التي تحول أنواع .NET (على سبيل المثال، System.String) إلى ومن العديد من الأنواع والمؤشرات غير المُدارةLPWSTR (على سبيل المثال، أو void*) للسماح بالاتصال بالكود غير المُدار . معظم هذه الطرق لها نفس متطلبات أذونات الأمان مثل الكود غير المُدار، حيث يمكنها التأثير على أماكن عشوائية في الذاكرة.

كوبول

تدعم لغة برمجة COBOL المؤشرات إلى المتغيرات. تعتمد كائنات البيانات الأولية أو الجماعية (السجلات) المعلنة داخل LINKAGE SECTIONالبرنامج على المؤشرات بطبيعتها، حيث تكون الذاكرة المخصصة الوحيدة داخل البرنامج هي مساحة لعنوان عنصر البيانات (عادةً كلمة ذاكرة واحدة). في كود مصدر البرنامج، تُستخدم عناصر البيانات هذه تمامًا مثل أي WORKING-STORAGEمتغير آخر، ولكن يتم الوصول إلى محتوياتها ضمنيًا بشكل غير مباشر من خلال مؤشراتها LINKAGE.

يتم عادةً تخصيص مساحة الذاكرة لكل كائن بيانات مشار إليه بشكل ديناميكي باستخدام CALLعبارات خارجية أو عبر هياكل لغوية ممتدة مضمنة مثل عبارات EXEC CICSأو EXEC SQL.

توفر الإصدارات الموسعة من لغة COBOL أيضًا متغيرات مؤشر معلنة باستخدام USAGE IS POINTERعبارات. يتم إنشاء قيم مثل هذه المتغيرات المؤشرية وتعديلها باستخدام عبارات SETو SET ADDRESS.

توفر بعض الإصدارات الموسعة من COBOL أيضًا PROCEDURE-POINTERمتغيرات قادرة على تخزين عناوين التعليمات البرمجية القابلة للتنفيذ .

ب ل/ي

توفر لغة PL/I دعمًا كاملاً للمؤشرات لجميع أنواع البيانات (بما في ذلك المؤشرات إلى الهياكل)، والتكرار ، وتعدد المهام ، ومعالجة السلاسل، والوظائف المضمنة الشاملة . كانت لغة PL/I قفزة إلى الأمام مقارنة بلغات البرمجة في وقتها. [ بحاجة لمصدر ] مؤشرات PL/I غير منمقة، وبالتالي لا يلزم إجراء أي تحويل لإلغاء مرجع المؤشر أو تعيينه. صيغة إعلان المؤشر هي DECLARE xxx POINTER;، والتي تعلن عن مؤشر باسم "xxx". تُستخدم المؤشرات مع BASEDالمتغيرات. يمكن إعلان متغير أساسي باستخدام محدد موقع افتراضي ( DECLARE xxx BASED(ppp);أو بدون ( DECLARE xxx BASED;)، حيث xxx هو متغير أساسي، والذي قد يكون متغير عنصر أو بنية أو مصفوفة، وppp هو المؤشر الافتراضي). يمكن توجيه مثل هذا المتغير بدون مرجع مؤشر صريح ( xxx=1;، أو يمكن توجيهه بمرجع صريح إلى المحدد الافتراضي (ppp)، أو إلى أي مؤشر آخر ( qqq->xxx=1;).

لا تعد العمليات الحسابية باستخدام المؤشر جزءًا من معيار PL/I، ولكن العديد من المترجمين يسمحون بتعبيرات من النموذج ptr = ptr±expression. كما يحتوي IBM PL/I على وظيفة مدمجة PTRADDلإجراء العمليات الحسابية. يتم إجراء العمليات الحسابية باستخدام المؤشر دائمًا بالبايتات.

تحتوي مُجمِّعات IBM Enterprise PL/I على شكل جديد من المؤشرات المكتوبة يُسمى HANDLE.

د

لغة البرمجة D هي مشتقة من لغة C و C++ والتي تدعم بشكل كامل مؤشرات C وأنواع C.

ايفل

تستخدم لغة Eiffel الموجهة للكائنات دلالات القيمة والمرجع دون حساب المؤشر. ومع ذلك، يتم توفير فئات المؤشر. وهي توفر حساب المؤشر، والتحويل إلى أنماط، وإدارة الذاكرة الصريحة، والتفاعل مع البرامج غير التابعة لـ Eiffel، وميزات أخرى.

فورتران

قدمت لغة Fortran-90 إمكانية مؤشر مكتوبة بشكل قوي. تحتوي مؤشرات Fortran على أكثر من مجرد عنوان ذاكرة بسيط. كما أنها تغلف الحدود الدنيا والعليا لأبعاد المصفوفة، والخطوات (على سبيل المثال، لدعم أقسام المصفوفة التعسفية)، والبيانات الوصفية الأخرى. يتم استخدام عامل الارتباط ، =>لربط a POINTERبمتغير يحتوي على TARGETسمة. يمكن أيضًا استخدام بيان Fortran-90 ALLOCATEلربط مؤشر بكتلة من الذاكرة. على سبيل المثال، يمكن استخدام الكود التالي لتحديد وإنشاء بنية قائمة مرتبطة:

النوع real_list_t 
real :: sample_data ( 100 ) النوع ( real_list_t المؤشر :: next => null () نهاية النوع    
         


النوع ( real_list_t الهدف :: my_real_list النوع ( real_list_t المؤشر :: real_list_temp    
    

real_list_temp => my_real_list قم   بقراءة ( 1 ، iostat = ioerr ) real_list_temp % sample_data إذا ( ioerr /= 0 ) الخروج   تخصيص ( real_list_temp % next ) real_list_temp => real_list_temp % next إنهاء قم بـ  

  
      
 
    

يضيف Fortran-2003 دعمًا لمؤشرات الإجراءات. كما يدعم Fortran-2003، كجزء من ميزة التوافق بين لغات C ، وظائف جوهرية لتحويل مؤشرات بنمط C إلى مؤشرات بنمط Fortran والعكس.

يذهب

تحتوي لغة Go على مؤشرات. وقواعد إعلانها تعادل قواعد إعلان لغة C، ولكنها مكتوبة بطريقة معاكسة، وتنتهي بالنوع. وعلى عكس لغة C، تحتوي لغة Go على ميزة جمع القمامة، ولا تسمح بحسابات المؤشر. ولا توجد أنواع مرجعية، كما هو الحال في لغة C++. وبعض الأنواع المضمنة، مثل الخرائط والقنوات، تكون محصورة (أي أنها داخليًا عبارة عن مؤشرات إلى هياكل قابلة للتغيير)، ويتم تهيئتها باستخدام الدالة make. وفي نهج لبناء قواعد موحدة بين المؤشرات وغير المؤشرات، ->تم إسقاط عامل السهم ( ): يشير عامل النقطة على المؤشر إلى الحقل أو الطريقة الخاصة بالكائن الذي تمت إزالة المرجع منه. ومع ذلك، لا يعمل هذا إلا مع مستوى واحد من الإحالة غير المباشرة.

جافا

لا يوجد تمثيل صريح للمؤشرات في Java . بدلاً من ذلك ، يتم تنفيذ هياكل البيانات الأكثر تعقيدًا مثل الكائنات والمصفوفات باستخدام المراجع . لا توفر اللغة أي مشغلات معالجة صريحة للمؤشرات. لا يزال من الممكن أن يحاول الكود إلغاء مرجع مرجع فارغ (مؤشر فارغ)، ومع ذلك، مما يؤدي إلى طرح استثناء وقت التشغيل . يتم استرداد المساحة التي تشغلها كائنات الذاكرة غير المرجعية تلقائيًا بواسطة جمع القمامة وقت التشغيل. [20]

نموذج 2

يتم تنفيذ المؤشرات بشكل مشابه جدًا لما هو موجود في باسكال، كما هو الحال VARمع المعلمات في استدعاءات الإجراءات. تتميز Modula-2 بنوعية أقوى من باسكال، مع طرق أقل للهروب من نظام النوع. تتضمن بعض المتغيرات من Modula-2 (مثل Modula-3 ) جمع القمامة.

أوبيرون

كما هو الحال مع Modula-2، تتوفر المؤشرات. لا تزال هناك طرق أقل للتهرب من نظام النوع، وبالتالي فإن Oberon ومتغيراته لا تزال أكثر أمانًا فيما يتعلق بالمؤشرات من Modula-2 أو متغيراتها. كما هو الحال مع Modula-3 ، فإن جمع القمامة هو جزء من مواصفات اللغة.

باسكال

على عكس العديد من اللغات التي تتميز بالمؤشرات، فإن لغة باسكال ISO القياسية تسمح فقط للمؤشرات بالإشارة إلى المتغيرات التي تم إنشاؤها ديناميكيًا والتي تكون مجهولة ولا تسمح لها بالإشارة إلى المتغيرات الثابتة أو المحلية القياسية. [21] ليس لديها حساب مؤشر. يجب أن يكون للمؤشرات أيضًا نوع مرتبط والمؤشر إلى نوع واحد غير متوافق مع مؤشر إلى نوع آخر (على سبيل المثال، المؤشر إلى حرف غير متوافق مع مؤشر إلى عدد صحيح). يساعد هذا في القضاء على مشكلات أمان النوع المتأصلة في تنفيذات المؤشر الأخرى، وخاصة تلك المستخدمة في PL/I أو C. كما أنه يزيل بعض المخاطر الناجمة عن المؤشرات المعلقة ، ولكن القدرة على التخلي ديناميكيًا عن المساحة المرجعية باستخدام الإجراء القياسي (الذي له نفس تأثير وظيفة المكتبة الموجودة في C ) تعني أن خطر المؤشرات المعلقة لم يتم القضاء عليه تمامًا. [22]disposefree

ومع ذلك، في بعض تطبيقات المترجم التجارية والمفتوحة المصدر لـ Pascal (أو مشتقاته) — مثل Free Pascal ، [23] Turbo Pascal أو Object Pascal في Embarcadero Delphi — يُسمح للمؤشر بالإشارة إلى متغيرات ثابتة أو محلية قياسية ويمكن تحويله من نوع مؤشر إلى آخر. علاوة على ذلك، فإن حساب المؤشر غير مقيد: يؤدي إضافة أو طرح مؤشر إلى تحريكه بهذا العدد من البايتات في أي اتجاه، ولكن استخدام الإجراءات القياسية Incأو Decمعه يحرك المؤشر بحجم نوع البيانات الذي تم إعلانه للإشارة إليه. يتم أيضًا توفير مؤشر غير محدد تحت الاسم Pointer، وهو متوافق مع أنواع المؤشرات الأخرى.

بيرل

تدعم لغة برمجة بيرل المؤشرات، على الرغم من ندرة استخدامها، في شكل وظائف التعبئة وفك التعبئة. وهذه الوظائف مخصصة فقط للتفاعلات البسيطة مع مكتبات أنظمة التشغيل المترجمة. وفي جميع الحالات الأخرى، تستخدم بيرل المراجع ، والتي تكون مكتوبة ولا تسمح بأي شكل من أشكال العمليات الحسابية للمؤشرات. وتُستخدم لبناء هياكل بيانات معقدة. [24]

انظر أيضا

ملحوظات

  1. ^ تسمح بعض المترجمات بتخزين عناوين الوظائف في مؤشرات فارغة. تسرد معايير C++ تحويل مؤشر وظيفة إلى void*كميزة مدعومة بشروط، وتنص معايير C على أن مثل هذه التحويلات هي "امتدادات مشتركة". وهذا مطلوب من قبل وظيفة POSIXdlsym . [15]

مراجع

  1. ^ دونالد كنوث (1974). "البرمجة المنظمة باستخدام عبارات الانتقال إلى" (PDF) . استبيانات الحوسبة . 6 (5): 261–301. CiteSeerX  10.1.1.103.6084 . doi :10.1145/356635.356640. S2CID  207630080. مؤرشف من الأصل (PDF) في 24 أغسطس 2009.
  2. ^ Reilly, Edwin D. (2003). Milestones in Computer Science and Information Technology . Greenwood Publishing Group. ص. 204. ISBN 9781573565219. تم الاسترجاع في 2018-04-13 . مؤشر هارولد لوسون.
  3. ^ "قائمة جوائز جمعية مهندسي الكهرباء والإلكترونيات للكمبيوتر". Awards.computer.org. مؤرشف من الأصل في 2011-03-22 . تم الاسترجاع في 2018-04-13 .
  4. ^ ISO/IEC 9899، البند 6.7.5.1، الفقرة 1.
  5. ^ ISO/IEC 9899، البند 6.7.8، الفقرة 10.
  6. ^ ISO/IEC 9899، البند 7.17، الفقرة 3: NULL... والذي يتوسع إلى ثابت مؤشر فارغ محدد بواسطة التنفيذ...
  7. ^ ISO/IEC 9899، البند 6.5.3.2، الفقرة 4، الحاشية السفلية 87: إذا تم تعيين قيمة غير صالحة للمؤشر، فإن سلوك عامل التشغيل الأحادي * يكون غير محدد... من بين القيم غير الصالحة لإلغاء الرجوع إلى مؤشر بواسطة عامل التشغيل الأحادي * مؤشر فارغ...
  8. ^ ab Plauger, PJ ; Brodie, Jim (1992). ANSI and ISO Standard C Programmer's Reference . Redmond, WA: Microsoft Press. ص 108، 51. ISBN 978-1-55615-359-4لا يحتوي نوع المصفوفة على ثغرات إضافية لأن جميع الأنواع الأخرى تتكدس بإحكام عند تكوينها في مصفوفات [ في الصفحة 51]
  9. ^ WG14 N1124، C – المعايير المعتمدة: ISO/IEC 9899 – لغات البرمجة – C، 2005-05-06.
  10. ^ يونج، رالف. "المؤشرات معقدة الجزء الثاني، أو: نحن بحاجة إلى مواصفات لغوية أفضل".
  11. ^ يونج، رالف. "المؤشرات معقدة، أو: ما الذي يوجد في البايت؟".
  12. ^ براءة اختراع أمريكية رقم 6625718، شتاينر، روبرت سي. (برومفيلد، كولورادو)، "المؤشرات النسبية لمواقعها الحالية"، صدرت في 2003-09-23، وتم تخصيصها لشركة Avaya Technology Corp. (باسكينج ريدج، نيوجيرسي) 
  13. ^ براءة اختراع أمريكية رقم 6115721، ناجي، مايكل (تامبا، فلوريدا)، "نظام وطريقة لحفظ قاعدة البيانات واستعادتها باستخدام مؤشرات ذاتية"، صدرت في 5 سبتمبر 2000، وتم تخصيصها لشركة IBM (أرمونك، نيويورك) 
  14. ^ "مؤشرات أساسية". Msdn.microsoft.com . تم الاسترجاع في 2018-04-13 .
  15. ^ "CWG Issue 195". cplusplus.github.io . تم الاسترجاع في 2024-02-15 .
  16. ^ "مؤشرات إلى الدوال الأعضاء". isocpp.org . تم الاسترجاع في 2022-11-26 .
  17. ^ “c++filt(1) – صفحة دليل Linux”.
  18. ^ "Itanium C++ ABI".
  19. ^ أولف بيلتنج، جان سكانشولم، “Vägen until C” (الطريق إلى C)، الطبعة الثالثة، الصفحة 169، ISBN 91-44-01468-6 
  20. ^ نيك بارلانتي، [1]، مكتبة تعليم علوم الكمبيوتر بجامعة ستانفورد، ص 9-10 (2000).
  21. ^ ISO 7185 Pascal Standard (نسخة غير رسمية)، القسم 6.4.4 أنواع المؤشرات المؤرشفة في 2017-04-24 على موقع Wayback Machine وما تلاها.
  22. ^ ج. ويلش، و دبليو جيه سنيرنجر، و كار هوار، "الغموض وعدم الأمان في باسكال"، البرمجيات: الممارسة والخبرة 7 ، ص 685-696 (1977)
  23. ^ دليل مرجعي مجاني للغة باسكال، القسم 3.4 المؤشرات
  24. ^ تفاصيل الاتصال. "// إنشاء المراجع (مراجع بيرل وهياكل البيانات المتداخلة)". Perldoc.perl.org . تم الاسترجاع في 2018-04-13 .
  • ورقة معالجة قائمة PL/I من إصدار يونيو 1967 من مجلة CACM
  • cdecl.org أداة لتحويل إعلانات المؤشر إلى اللغة الإنجليزية البسيطة
  • دليل للمبتدئين على IQ.com يصف المؤشرات باللغة الإنجليزية البسيطة.
  • المؤشرات والذاكرة مقدمة عن المؤشرات – مكتبة تعليم علوم الكمبيوتر بجامعة ستانفورد
  • المؤشرات في برمجة C أرشيف 2019-06-09 على موقع Wayback Machine نموذج مرئي للمبتدئين في برمجة C
  • 0pointer.de قائمة موجزة من أكواد المصدر ذات الطول الأدنى التي تزيل مرجع مؤشر فارغ في العديد من لغات البرمجة المختلفة
  • "كتاب C" - يحتوي على أمثلة للمؤشرات في ANSI C
  • اللجنة الفنية المشتركة ISO/IEC JTC 1، اللجنة الفرعية SC 22، مجموعة العمل WG 14 (2007-09-08). المعيار الدولي ISO/IEC 9899 (PDF) . {{cite book}}: |work=تم تجاهله ( مساعدة ) .CS1 maint: أسماء متعددة: قائمة المؤلفين ( الرابط ) CS1 maint: أسماء رقمية: قائمة المؤلفين ( الرابط )
تم الاسترجاع من "https://en.wikipedia.org/w/index.php?title=المؤشر_(برمجة_الحاسوب)&oldid=1251314028"
Original text
Rate this translation
Your feedback will be used to help improve Google Translate