قسم الميكروكنترولر والروبوت ودوائر الاتصال بالحاسب الالي قسم المتحكمات الـ microcontroller و المعالجات microprocessor و التحكم الرقمي بالكمبيوتر CNC والانظمة الآلية والروبوت Robots

أدوات الموضوع

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:37 PM المشاركة 1   
افتراضي المؤشرات Pointers : Twitter FaceBook Google+



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

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

عامل المرجعية (&)Reference Operator :

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:40 PM المشاركة 2   
افتراضي


عامل المرجعية (&)Reference Operator :

يمكن الحصول على "عنوان المتغير" عن طريق سبق (تقديم) اسم المتغير بعلامة العطف (&) ، والمعروفة باسم "عامل المرجعية" ، والذى يمكن ترجمته حرفيا بأنه "عنوان ال" . على سبيل المثال :

كود:
foo = &myvar;

وهذا من شأنه تخصيص "قيمة عنوان المتغير myvar " ( &myvar) إلى "قيمة المتغير foo " (foo) ، عن طريق سبق اسم المتغير myvar بعامل المرجعية &، فإننا لا نخصص محتوى المتغير نفسه إلى foo ، ولكن نخصص عنوانه .
العنوان الفعلى للمتغير بالذاكرة "لا يمكن معرفته قبل وقت التشغيل" ، ولكن دعونا نفترض ، من أجل المساعدة فى توضيح بعض المفاهيم ، أن المتغير myvar قد وضع أثناء وقت التشغيل بعنوان الذاكرة (1776) .
فى هذه الحالة اعتبر قطعة الكود الصغيرة التالية :

كود:
myvar = 25;
foo = &myvar;
bar = myvar;

القيم المحتواة بكل متغير بعد تنفيذ هذا الجزء تكون كما هو مبين بالمخطط التالى :









· فى البداية ، بعبارة تخصيص ، خصصنا القيمة (25) إلى المتغير myvar ( أصبحت محتوياته 25 وعنوانه ، الذى فرضناه ، بالذاكرة هو 1776 ) .
· ثم ، بعبارة تخصيص ثانية ، خصصنا قيمة عنوان المتغير myvar إلى المتغير foo ، الذى فرضنا أنه 1776 (أصبحت "محتويات" المتغير foo بالقيمة 1776) .
· وأخيرا ، وبعبارة تخصيص ثالثة ، خصصنا القيمة المحتواة بالمتغير myvar (وهى 25 ) إلى المتغير bar (ليصبح محتواه 25 ) . وهذه هى عبارة التخصيص القياسية التى نعرفها جيدا .
الفرق بين عبارة التخصيص الثانية وعبارة التخصيص الثالثة هو ظهور معامل المرجعية (&) .
"المتغير الذى يخزن عنوان متغير آخر يسمى مؤشر Pointer " ، مثل المتغير foo فى المثال السابق . المؤشرات هى ميزة قوية جدا فى لغة السى . لاحقا سوف نتناول طريقة إعلان واستخدام المؤشرات .

عامل إلغاء المرجعية Dereference ( * ) :

اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )
  

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:50 PM المشاركة 3   
افتراضي


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

كود:
baz = *foo;

يمكن أن تقرأ على النحو التالى : "قيمة المتغير baz "تساوى "القيمة المشار إليها بالمتغير foo" ، وسوف تقوم العبارة فعليا بتخصيص القيمة 25 إلى المتغير baz ، حيث أن المتغير foo قيمته 1776 ، والقيمة المشار إليها بواسطة 1776 سوف تكون 25 ( فى أعقاب المثال أعلاه) .

من المهم أن نفرق بوضوح بين أن المتغير foo يشير إلى القيمة 1776 ، فى حين أن (*foo) (مع وجود * تسبق اسم المتغير) تشير إلى القيمة المخزنة عند العنوان 1776 ، وهذه القيمة فى هذه الحالة هى 25 . لاحظ الفرق بين تضمين أو عدم تضمين عامل إلغاء المرجعية كما هو مكتوب بالتعليقات على العبارات التالية :
كود:
baz = foo; // baz equal to foo (1776) baz = *foo; // baz equal to value pointed to by foo (25)
وبالتالى فإن عامل المرجعية وعامل إلغاء المرجعية هى عوامل مكملة أو متتامة :
· العامل & هو عامل المرجعية ، ويمكن قراءته كما يلى "عنوان ال .." .
· العامل * هو عامل إلغاء المرجعية ، ويمكن قراءته كما يلى "القيمة المشار إليها بواسطة ..." .
وبالتالى فإن لها معانى معكوسة : المتغير الذى يرجع إليه بالعامل & يمكن أن يتم إلغاء مرجعيته بالعامل * .
فى وقت سابق أجرينا عملتى التخصيص التالية :

كود:
myvar = 25; foo = &myvar;
بعد هذه العبارات مباشرة ، فإن جميع العبارات التالية تعطى "صواب" true كنتيجة :

كود:
myvar == 25 &myvar == 1776 foo == 1776 *foo == 25
· التعبير الأول واضح تماما ، باعتبار أن عملية التخصيص التى أجريت على المتغير myvar كانت myvar = 25 .
· التعبير الثانى يستخدم عامل المرجعية (&) ، والذى يعيد return عنوان المتغير myvar ، والذى فرضنا أن له القيمة 1776 .
· التعبير الثالث واضح إلى حد ما ، لأن التعبير الثانى كان صحيحا وأن عملية التخصيص التى أجريت على المتغير foo كانت foo = &myvar .
· التعبير الرابع يستخدم عامل إلغاء المرجعية (*) والذى يمكن قراءتع بالصيغة "القيمة المشار إليها بواسطة ..." ، والقيمة المشار إليها بالمتغير foo هى فى الواقع 25 .
لذلك ، وبعد كل ذلك ، يمكنك أيضا أن تستنتج أنه طالما أن العنوان المشار إلية بالمتغير foo لم يتغير ، فإن التعبير التالى سوف يكون صواب true أيضا :
كود:
*foo == myvar

إعلان (تعريف) المؤشرات Declaring Pointers :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:52 PM المشاركة 4   
افتراضي


إعلان (تعريف) المؤشرات Declaring Pointers :
نتيجة لقدرة المؤشر على الإشارة (الرجوع) مباشرة إلى القيمة التى يشير إليها ، فإن المؤشر له خصائص مختلفة عندما يشير إلى قيمة لحرف char عنه عندما يشير إلى قيمة لعدد صحيح int أو عدد حقيقى float . بمجرد إلغاء المرجعية ، فإن النوع ينبغى أن يكون معروفا . ولهذا ، فإن "إعلان المؤشر ينبغى أن يتضمن نوع البيانات التى سوف يشير إليها المؤشر .
إعلان المؤشرات يكون بالصيغة التالية :

كود:
type * name;
حيث النوع type هو نوع البيانات المشار إليها بواسطة المؤشر . هذا النوع ليس هو نوع المؤشر نفسه ، ولكن نوع البيانات التى يشير إليها المؤشر . على سبيل المثال :
كود:
int * number; char * character; double * decimals;

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

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

مثال على المؤشرات :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:55 PM المشاركة 5   
افتراضي


مثال على المؤشرات :
كود:
void main () { int firstvalue, secondvalue; int * mypointer; ………. ……… mypointer = &firstvalue; *mypointer = 10; mypointer = &secondvalue; *mypointer = 20; ………. ………. }

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

كود:
mypointer = &firstvalue;
· بعد ذلك ، "القيمة المشار إليها بواسطة المؤشر " *mypointer يخصص لها القيمة (10) كما يلى :
كود:
*mypointer = 10;
ولأنه ، عند هذه اللحظة ، المؤشر mypointer يكون مشيرا إلى موقع الذاكرة (عنوان) للمتغير firstvalue ، فإن هذا فى واقع الأمر يعدل من قيمة المتغير firstvalue .
· ولتوضيح أن المؤشر قد يشير إلى متغيرات مختلفة خلال فترة بقائه (حياته) فى البرنامج ، يتم تكرار العملية السابقة مع المتغير secondvalue وبنفس المؤشر mypointer كما يلى :
كود:
mypointer = &secondvalue; *mypointer = 20;

مثال آخر مفصل أكثر بعض الشىء :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 23-02-2014, 07:58 PM المشاركة 6   
افتراضي


مثال آخر مفصل أكثر بعض الشىء :
كود:
void main () { int firstvalue = 5, secondvalue = 15; int * p1, * p2; p1 = &firstvalue; // p1 = address of firstvalue p2 = &secondvalue; // p2 = address of secondvalue *p1 = 10; // value pointed to by p1 = 10 *p2 = *p1; // value pointed to by p2 = value pointed by p1 p1 = p2; // p1 = p2 (value of pointer is copied) *p1 = 20; // value pointed by p1 = 20 }



تتضمن كل عملية تخصيص تعليق على كيفية قراءة كل سطر : أى استبدال العامل (&) بواسطة الصيغة "عنون ال ...) ، واستبدال العامل ( * ) بالصيغة "قيمة المشار إليه بواسطة ...." .
لاحظ أن هناك تعبيرات مع المؤشرات p1و p2 ، كلاهما مع أو بدون عامل إلغاء المرجعية ( * ) . معنى التعبيير باستخدام عامل إلغاء المرجعية يختلف تماما عن تلك التى بدونه . عندما يسبق هذا العامل اسم مؤشر ، فإن التعبير يشير إلى القيمة المراد الإشارة إليها ، بينما يظهر اسم المؤشر بدون هذا العامل ، فإنه يشير إلى قيمة المؤشر نفسه ( أى عنوان ما يشير إليه المؤشر) .
شىء آخر قد يلفت انتباهك ، وهو السطر التالى :
كود:
int * p1, * p2;
هنا ، يتم إعلان المؤشرين المستخدمة فى المثال السابق . ولكن لاحظ أن هناك علامة النجمة ( * ) لكل مؤشر ، وذلك لأن كل منهما له النوع int ( مؤشر إلى متغير نوع العدد الصحيح int ) . وهذا يكون مطلوب نتيجة لقواعد الأسبقية . لاحظ أنه بدلا من ذلك كان الكود بالشكل التالى :
كود:
int * p1, p2;
فى الواقع ، p1 سوف يكون من النوع int* ، ولكن p2 سوف يكون من النوع int . المسافات لا تهم على الإطلاق لهذا الغرض . ولكن على أى حال ، ببساطة تذكر أن وضع علامة النجمة لكل مؤشر يكون كافيا لمغظم المستخدمين المهتمين بإعلان مؤشرات متعددة لكل عبارة . أو حتى من الأفضل : استخدام عبارات مختلفة من أجل كل متغير .
المؤشرات والمصفوفات :

إضافة رد

العلامات المرجعية

«     الموضوع السابق       الموضوع التالي    »
أدوات الموضوع

الانتقال السريع إلى


الساعة معتمدة بتوقيت جرينتش +3 الساعة الآن: 06:16 PM
موقع القرية الالكترونية غير مسؤول عن أي اتفاق تجاري أو تعاوني بين الأعضاء
فعلى كل شخص تحمل مسئولية نفسه إتجاه مايقوم به من بيع وشراء وإتفاق وأعطاء معلومات موقعه
التعليقات المنشورة لا تعبر عن رأي موقع القرية الالكترونية ولايتحمل الموقع أي مسؤولية قانونية حيال ذلك (ويتحمل كاتبها مسؤولية النشر)

Powered by vBulletin® Version 3.8.6, Copyright ©2000 - 2025