ahmed.o.mohamed

اختبر قدراتك في C/CPP - الحلقة الثانية, الجزء الثاني

6 ردود في هذا الموضوع

السلام عليكم

الحلقة الأولى.

الحلقة الثانية - الجزء الأول.

أهلا بكم في الجزء الثاني من الحلقة الثانية من سلسلة اختبر قدراتك, الحلقة الثانية سأكتبها على عدة أجزاء و ستكون خاصة بالمؤشرات.

أجزاء الحلقة الثانية ستكون مُرتبة حسب الصعوبة إن شاء الله.

الإختبار الثاني (الجزء الثاني ) :

لتكن لدينا التعريفات التالية :

char c[10], *s, **t;
int (*f)(), g(int);

struct st {
char **st_ch;
int (*st_pf)();
} *stp;

العبارات التالية, هل هي صحيحة ؟

s = c++;
*++t = s;
*t[8] = c[2];
*t = *++s;
*t++ = *--s;
f++ = g;
f = g;
*f = g;
s = (char *) f;
f = (int (*)())s;
f = stp->st_pf;
**stp->st_ch = c[0];
**(stp->st_ch) = s;
stp = (struct st *) *t;
stp = (struct st *)c;
f = (int (*)())stp->st_ch;

  • إذا كان الجواب نعم, ماذا تُمثل العبارة الصحيحة ؟
  • إذا كان الجواب لا !, ما تعليلك ؟

سأضع حل السؤال بعد الإنتهاء من عرض المحاولات.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

والله أسئلة صعبة ... لا أحب هذه النوعية .. فأنا لا أستخدم هذه الطريقة في الكتابة أبداً ... (تصيب المبرمج بالصداع النصفيwacko.gif )..

على أي حال هذه محاولتي ..


char c[10], *s, **t;
int (*f)(), g(int);

struct st {
char **st_ch;
int (*st_pf)();
} *stp;


s = c++;//خاطئة لا يسمح بتغيير عنوان المؤشر لأنه مؤشر مضفوفة ثابتة
*++t = s;//خاطئة أسندنا قيمة حجرة غير محجوزةإلى حجرة محجوزة
*t[8] = c[2];//خاطئة المؤشر لم يحجز بعد أي مضفوفة حتى نسمح له باستخدام الحجرة8
*t = *++s;//خاطئة أسندنا قيمة المؤشر إلى حجرة غير محجوزة
*t++ = *--s;//خاطئة أسندنا قيمة حجرة غير محجوزة إلى حجرة غير محجوزة (خطأ مضاعف)ـ
f++ = g;//خاطئة إسناد حجرة غير محجوزة كما أن الطرف الأيسر مؤشر والأيمن قيمة معادة للتابع
f = g;//خاطئة الطرف الأيمن مشر والأيسر قيمة معادة للتابع
*f = g;//خاطئة يجب وضع &في الطرف الأيمن وليس *في الطرف الأيسر
s = (char *) f;//تحويل خاطئ لا يمكن التحويل بين أنواع المؤشرات هكذا
f = (int (*)())s;//يا إلهي ما هذا لم أر مثل هذا في حياتي أعتقد أنه خاطئ لنفس السبب السابق
f = stp->st_pf;//صحيحة أصبح مؤشر التابع على اليسار له نفس جسم التابع في الكائن من البنية
**stp->st_ch = c[0];//خاطئة إسناد حجرة غير محجوزة إلى حجرة محجوزة
**(stp->st_ch) = s;//خاطئة إسناد قيمة إلى مؤشر
stp = (struct st *) *t;//كيف يمكن للكومبايلر أن يقوم بهذا التحويل
stp = (struct st *)c;//نفس السابق ولو أنني أظن إجابتي خاطئة
f = (int (*)())stp->st_ch;//لا حول ولا قوة إلا بالله

يا إلهي ما هذه لصعوبة ...!!!!

أشك في معظم إجاباتي ... ولكن هذا هو مستواي الحالي في المؤشرات على أي حال ...كنت أحب المؤشرات .. لا تجعلني أكرهها happy.gif ....

تم تعديل بواسطه مصطفى 36a2
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

[#10222] غير مصرح لك بإستخدام الرسائل الخاصة

:blink:

s = c++;

لا, عنوان c لا يمكن تغييره

*++t = s;

نعم, عنوان المصفوفة الثانية في سلسلة المصفوفات t سيصبح مساوي لـ s

*t[8] = c[2];

نعم, الحرف الأول في السلسلة التاسعة (t[8][0]) سيأخذ قيمة الحرف الثالث في المصفوفة c

*t = *++s;

لا, إسناد char إلى مؤشر

*t++ = *--s;

لا, إسناد char إلى مؤشر

f++ = g;

لا, اسناد دالة لمؤشر دالة

f = g;

لا, اسناد دالة لمؤشر دالة

*f = g;

لا, اختلاف في نوع البارماترات

s = (char *) f;

نعم, أظن الـ cast راح تشتغل عادي و نقدر نعمل كاست من مؤشر دالة لمؤشر char

f = (int (*)())s;

نعم, كاست للمؤشر s بحيث يصير نوعه مؤشر لدالة ترجعint و ما تأخذ أي بارمتر, على ما أظن

f = stp->st_pf;

نعم, مؤشر الدالة st_pf له نفس نوع f

**stp->st_ch = c[0];

نعم, الحرف الأول في السلسة الأولى في st_ch راح ياخذ قيمة الحرف الأول في السلسلة c

**(stp->st_ch) = s;

لا, اسناد *char إلى char

stp = (struct st *) *t;

نعم, كاست لمحتوى t* و هو عبارة عن *char إلى مؤشر من نوع (struct st *) راح تصلح أظن

stp = (struct st *)c;

نعم, نفس السبب, كاست مؤشر لمؤشر ممكن تصلح

f = (int (*)())stp->st_ch;

نعم,ممكن الكاست لـ stp->st_ch و هو **char إلى int (*)() راح تصلح

تم تعديل بواسطه khatibe_30
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

وعليكم السلام أخي أحمد

لن أنسى أن أشكرك على هذه الأسئلة التثقيفية التي بدون شك سترفع من مستوانا و تكشف أخطائنا وهفواتنا

فلنبدأ على بركة اللهcool.gif

2-الحالة الأولى خاطئة

s = c++;

في هذه الحالة c يتحول لمؤشر ثابت يؤشر على أول مكون للمصفوفة

int c[10] --> int *const p=&c[0];

وبالتالي لا يمكننا القيام بمؤثر الزيادة

c++;

لأنه lvalue غير قابلة للتعديل

2-الحالة الثانية صحيحة

*++t = s;

t مؤشر لمؤشر و القيمة التي ستسند له هي عنوان مؤشر

هكذا

t=&s;

و s مؤشر والقيمة التي ستسند له عي عنوان متغير

و قيمة *t ستكون نفس قيمة المؤشر s أي عنوان لمتغير

int *s=NULL;
int **t=NULL;

t=&s; // ==> *t=s;

ولك أن تتأكد من هذا المثال

	int a=5;
int *s=&a;
int **t=&s;
printf("s=%p\n*t=%p",s,*t);

3-الحالة الرابعة خاطئة

*t = *++s;

t مؤشر يؤشر لعنوان مؤشر بينما s مؤشر يؤشر لعنوان متغير

*s يأخد كقيمة (قيمة لمتغير) بينما *t يأخد كقيمة قيمة المؤشر الأول أي عنوان لمتغير

4-الحالة الخامسة خاطئة

*t++ = *--s;

نفس الشيء بالنسبة للحالة الرابعة الفرق فقط أننا استعملنا مؤثرات الزيادة و النقصان

سأقفز على مؤشرات الدوال happy.gif

ونتوجه مباشرة لهذه الحالة

stp = (struct st *)c;

كلنا نعرف أن struct هو نوع خاص من المصفوفات إلا أن الفرق بينهما هو أن المصفوفة تحتوي مكونات من نفس النوع

بينما struct يحوي مكونات من مختلف الأنواع

stp = (struct st *)c;

stp مؤشر من نوع struct st

و قمنا بتحويل قصري cast للمصفوفة cإلى مؤشر من نوع struct st وهنا لن يظهر أي خطأ في الكومبيلر

ولله أعلم laugh.gif

تحياتي و بالتوفي للآخرين

تم تعديل بواسطه مومو (momo)
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

العبارة الأولى خاطئة لأن الــ Lvalue غير قابلة للتعديل كما قال الأخ مومو.

العبارة الثانية صحيحة من ناحية الــ Syntax لكن خاطئة من ناحية الــ Logic, لأنه تم إسناد عنوان s للمؤشر الذي يقع بعد t و ليس t نفسه, و هنا يكمن الخطأ ! لأن المؤشر t لا يملك حق الوصول إلى الخانة الموالية. أيضا المؤشر s لم يملك بعد عنوانا في الذاكرة.

العبارة الثالثة خاطئة, لأننا لم نحجز بعد ذاكرة مصفوفة للمؤشر t.

العبارة الرابعة خاطئة لسببين, الأول هو محاولة الوصول إلى الخانة الموالية لــ s و الخطأ الثاني هو محاولة إسناد قيمة متغير لعنوان مؤشر.

العبارة الخامسة خاطئة, لسببين أيضا, الأول هو محاولة إسناد قيمة متغير إلى عنوان مؤشر و الخطأ الثاني هو محاولة الوصول إلى كل من, العنوان الموالي لــ t و العنوان الموجود قبل s.

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

العبارة السابعة و الثامنة خاطئتان لعدم تطابق طرفي الإسناد.

العبارة التاسعة صحيحة 100%, يمكنكم التأكد من خلال الكود التالي :

#include<stdio.h>

int main() {
char ch = 'A', *chPtr;
int (*fPtr)();
chPtr = &ch;
printf("ch = %d, chPtr = %p, fPtr = %p\n", ch, chPtr, fPtr);
chPtr = (char *) fPtr;
printf("ch = %d, chPtr = %p, fPtr = %p\n", ch, chPtr, fPtr);
return 0;
}

العبارة العاشرة تمثل عكس الحالة السابقة :

#include<stdio.h>

int main() {
char ch = 'A', *chPtr;
int (*fPtr)();
chPtr = &ch;
printf("ch = %d, chPtr = %p, fPtr = %p\n", ch, chPtr, fPtr);
fPtr = (int (*)())chPtr;
printf("ch = %d, chPtr = %p, fPtr = %p\n", ch, chPtr, fPtr);
return 0;
}

العبارة الحادية عشر صحيحة نظرا لتطابق طرفي الإسناد.

العبارة الثانية عشر صحيحة من ناحية الــ Syntaxe لكن خاطئة من ناحية الــ Logic, نظرا لمحاولة الوصول إلى ذاكرة غير محجوزة.

العبارة الثالثة عشر خاطئة لعدم تطابق طرفي الإسناد.

العبارة الرابعة عشر صحيحة, مجرد تحويل بين مؤشر من نوع char * إلى مؤشر من نوع struct st *.

العبارة الخامسة عشر و السادسة عشر صحيحتان, نفس الفكرة السابقة.

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

تم منح النقاط للمشاركات المفيدة و حذف الردود الغير مفيدة, حفاظا على تنسيق الموضوع.

يُغلق.

أراكم في الجزء الثالث من الحلقة الثانية.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .