recent
أخبار ساخنة

المؤشرات Pointers و إستخداماتها في لغة السي C الدرس|19|

الصفحة الرئيسية


المؤشرات Pointers في لغة السي C

سوف نتعرَّف اليوم على خاصية مهمة جداً في لغة سي و هذه الخاصية تميز هذه اللغه عن غيرها من اللغات لكونها تُمثِّل المبرمج من تنظيم الذاكرة بشكل اكبر و افضل أثناء تنفيذ البرنامج مقارنة مع اللغات الأُخرى, و هو ما جعل لغة سي لغه مُتقدمة يمكن إستخدامها في برمجة نُظُم التشغيل أو البرمجيات المتطورة الأٌخرى, تُسمى هذه الخاصية بالمؤشرات Pointers.


تخزين القيم في الذاكرة

يُمكنك تخيل الذاكرة على أجهزة الكمبيوتر على أنها مصفوفة كبيرة تحتوي على بيانات مُعينة بحجم 1 بايت, مثلاً لو قٌلنا أن جهاز معين سعة ذاكرة الوصول العشوائية RAM تكون 2GB و الغيغا تعني مليار فهذا يعني أن ذاكرة الوصول العشوائية لهذا الجهاز يُمكن تخزين 2 مليار بايت و طبعاً البيانات الموجودة في الذاكرة قد تكون من تخزين إما من نظام التشغيل لها OS أو من قبل برنامج معين يتم تنفيذه.

كيف يتم الوصول إلى مكان مُعين في الذاكرة و تخزين القيم فيه أو إسترجاعها؟

إن لكل موقع في الذاكرة عنوان Address مُعيَّن يُستخدم للوصول إلى هذا الموقع في أي وقت, مثلاً نُركز بالشكل الآتي


في الشكل السابق نُلاحظ أنَّ الموقع صاحب العنوان 0 يحتوي على القيمة 23 و الموقع صاحب العنوان 1 يحتوي على القيمة 26 و الموقع صاحب العنوان 2 يحتوي على القيمة 27 و هكذا......الخ.

لنتذكَّر معاً ما تعلّمناه سابقاً عن كيفية تخزين المُتغيرات في الذاكرة, لنُلقي نظرة للشكل الآتي


عند تعريفنا لمُتغير ما يتم حجز مكان معيَّن له في الذاكرة خاص في هذا المتغير, و يبدر الذكر هُنا أن نوع البيانات int و هو من حجم 2 بايت, فإنه سيحتل مكانين فقط في الذاكرة و ليس مكان واحد, لكن بغرض التبسيط هنا في هذا الدرس سنفترض أنه مكان واحد فقط حتى الآن.

إن قُمنا بإستدعاء هذا المتغير من خلال إسمه فإن القيمة المخزَّنة فيه هي التي سيتم إرجاعها إلينا

int x = 23;
printf("%d", x);

ففي الكود السابق int x يُساوي 23 ثم طبعنا الـ x و سوف يطبع لنا 23, و لكن كيف لنا بإسترجاع عنوان هذا الموقع, موقع المتغير x الذي تم تخزين القيمة فيه بدلاً من القيمة نفسها؟

يتم ذلك بمجرد إضافة علامة & قبل إسم المتغير

int x = 23;
printf("%p", &x);

 

و طبعاً علامة & تختلف عن علامة & المستخدمة في العمليات المنطقية فهي ذات معنى آخر هنا, و تم تغيير d إلى p يعني أننا نُريد مكان هذا المتغير و الحرف p إختصار للكلمة pointer و يعني المكان الذي يعيش به المتغير.

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

int main(int argc, char** argv)
{
    int x = 23;
    printf("%p", &x);

    return 0;
}


شرح المثال السابق 1

أنشأنا مُتغير عددي int إسمه x و قيمته 23 ثم طلبنا طباعة مكان تواجد أو أين يسكُن هذا المتغير في الذاكرة عبر %p ثم وضعنا إشارة & قبل إسم المتغير, و عند تشغيل هذا البرنامج سنحصل على النتيجة


لقد طبع لنا المكان 0x7fffc3fd286c حيث يسكُن فيه المٌتغير x في هذا المكان و هو من نوع hexadecimal أي الست عشري, أي أن الأرقام تكون من 0 حتى F و بداية الموقع كان 0x و هو ليس من ضمن الموقع لهذا المتغير, يُمكن التعرف على النظام الست عشري بمشاهدة الفيديو الآتي

 

تخزين عناوين المتغيرات في المؤشرات

تعلَّمنا قبل قليل عن كيفية طباعة عنوان مُتغير ما, لكن كيف لنا أن نستخدم هذا العنوان عدا عن مجرد طباعته, فهل يُمكننا تخزين هذا العنوان لإستخدامه لآحقاً كما في المتغيرات العادية؟

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

 

فهذه النجمة تدل على أن هذا المُتغير مخصص لتخزين العناوين و ليس القيم أي بخلاف المُتغير العادي الذي يُستخدَم لتخزين قيم, و في الصورة السابقة لدينا int x يساوي 9 و x هي متغير عادي يملك قيمة عادية من نوع int أما int*pointer يساوي 1 فهو مؤشر يقوم بالتأشير على العنوان 1 و لا يُمكننا كتابة المؤشر بهذا الشكل و سوف نرى هذا لآحقاً.

نظراً لكون المبرمج لا يرى ذاكرة الوصول العشوائية في جهاز الكمبيوتر و لا يعلَم ما هي البيانات المخزَّنة فيها و أين هي مخزنة, فمن غير العملي تحديد العنوان بصورة مباشرة كأنه قيمة عادية.

int x = 23;
int *pointer = &x;
printf("%p", pointer);


فلو أردنا تخزين عنوان المُتغير x في المؤشر المُسمى pointer نقوم بتعريف المؤشر بوضع إشارة النجمه * قبل إسمه و من ثم نقوم بتحديد قيمته و هي عنوان المُتغير x حيث نستخدم إشارة & لإسترجاع عنوان هذا المتغير.

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
    int x = 26;
    printf("X value = %d\n", x);
    printf("X address = %p\n", &x);
    return 0;
}

شرخ المثال السابق 2

قمنا بإنشاء مُتغير عددي و إسمه x و قيمته هي 26 ثم طلبنا طباعة المُتغير كما هي في العملية الأولى, و بعملية الطباعة الثانية قُمنا بطلب مكان سكن هذا المٌتغير في الذاكرة, و عند تشغيل هذا البرنامج سنحصل على نتيجتين كما يلي


السطر الأول هي قمية المتغير كقيمة عادية, أما السطر الثاني هو مكان تواجد هذا المُتغير في الذاكرة العشوائية RAM.

تخزين العنوان في متغير

يُمكننا أن نقوم بكتابة مكان تواجد المتغير في الذاكرة بمتغير آخر و هذا ما سوف نتعرف عليه بالمثال الآتي

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
    int x = 26;
    printf("X value = %d\n", x);
    printf("X address = %p\n", &x);
    int *xPointer = &x;
    printf("X Pointer = %p", xPointer);
    return 0;
}

شرح المثال السابق 3

قمنا بإنشاء مُتغير عددي و إسمه x و قيمته هي 26 ثم طلبنا طباعة المُتغير كما هي في العملية الأولى, و بعملية الطباعة الثانية قُمنا بطلب مكان سكن هذا المٌتغير في الذاكرة, ثم قُمنا بإنشاء متغير إسمه Pointer ووضعنا قبل الإسم علامة النجمة ثم كتبنا أن قيمة هذا المؤشر هي x ووضعنا علامة & قبل إسم المتغير, ثم طلبنا طباعة هذا المتغير كمتغير عادي و عند تشغيل هذا الكود ستكون النتيجة هي


كما لآحظنا في البداية طبع لنا قيمة المتغير كقيمة عادية و هي 26 ثم طبع لنا مكان تواجد هذا المتغير في الذاكرة و أخيراً قُمنا بتخزين مكان المتغير في متغير عادي.

إضغط للرجوع للدرس السابق

google-playkhamsatmostaqltradent