الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

إعادة توليد الأخطاء .. تمرير الوسطاء للدالة printf

بدأه مصطفى 36a2 في 20 أكتوبر 2013 · 2 رد · 602 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

 

عندما تظهر لك مشكلة برمجية عجيبة .. وتحجز لك دماغك لمدة ليست بالقصيرة .. فأسوأ ما يمكن أن يحدث هي أن تختفي لوحدها !!

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

 

لنبدأ ..

أثناء أحد البرامج .. بدأت دالة printf تظهر نتائج غريبة ... إليك الأسطر التالية :

for(int j=1;j*powers<m;j++)            {                int k=j*powers;                nums[k]=nums[j];                printf("%i\n",k);                printf("%i %i\n",powers,k);            }

عند الطباعة في الاستدعاء الأول تتم طباعة k بشكل طبيعي .. ولكن في الاستدعاء الثاني يطبع صفراً !!! ولكن عند تغيير ترتيب الوسطاء تتم طباعة k بشكل طبيعي !!

 

القاعدة الأولى في البرمجة : الحاسوب لا يخطئ .. أنت الذي تُخطئ ...

وطبعاً كانت المشكلة عويصة لمدة عشر دقائق .. قبل أن يتمكن أحدهم من إعادة توليد المشكلة في الكود التالي :

long long x=7;    int y=5;    printf("%i %i\n",x,y);

حاول تغيير ترتيب الوسطاء وتعجّب قليلا :)

 

 

فهل عرفت ما هي المشكلة :)

 

بالتوفيق

1
#2

هذه أخطاء اختيار النوع الخطأ للدوال التي تتطلب format مثل printf و scanf وغيرها، في المثال الأخير الدالة printf حسب الـformat تنتظر متغيرين int (أي 32 بت)، بينما ممر لها متغير int و متغير long long int (أي 64 بت)، وقتها ستعطي نتائج عشوائية تختلف حسب المعالج وحسب المصرف. في معالج 32 بت مع gcc عند كتابة:

  long long x = 7;  int y = 5;  printf("%i %i\n", x, y);

ستمرر لـprintf:

0x0000000000000007 0x00000005

ستطبع 7 ثم 0، الـ7 هي الجزء العلوي من x والـ0 الجزء السفلي من x، لن تطبع y إلا إذا زودت %i أخرى (هذا يعمل الا أنه يظل خطأ). عند عكس الترتيب سيبدو أنها أعطت نتيجة صحيحة 5 ثم 7:

  long long x = 7;  int y = 5;  printf("%i %i\n", y, x);

إلا أنها ستعطي نتيجة خاطئة لو استخدم رقم أكبر من 32 بت في x.

 

الحل هو استخدام الـformat الصحيح لـlong long وهو lld% أو lli% (ستجدها في الجدول):

  long long x = 7;  int y = 5;  printf("%lli %i\n", x, y);

ملاحظة، قد يعطي gcc تحذير خاطئ اذا كنت تستخدم نسخة قديمة منه على ويندوز إلا أن الكود صحيح.

تم تعديل هذه المشاركة بواسطة Mr.B في 20 أكتوبر 2013 في 21:17

2
#3

بارك الله فيك .. اجابة كاملة وتامة كما عوّدتنا أخي Mr.B  :)

بسبب الدراسة العشوائية غير الأكاديمية .. تصبح فقرات بسيطة ربما في كتاب .. اكتشافات تستحق الذكر بالنسبة لي D:

شكرا للرد الممتاز ..

وفقك الله :)

1

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…