فهم sizeof في C++: لماذا لا تساوي n 8؟

عند العمل مع المصفوفات في C++، قد تواجه نتائج غير متوقعة تتعلق بعملية sizeof، خاصة عند تمرير المصفوفات إلى الدوال. في هذا المقال، سنستكشف ارتباكًا شائعًا ينشأ عند استخدام sizeof مع معلمات الدوال، بالإجابة تحديدًا على السؤال: لماذا لا تساوي n 8 في الدالة foo()؟

المشكلة

دعونا نفحص قطعتين من الشيفرة التي توضح المشكلة:

المثال 1: الدالة foo()

void foo(char cvalue[8])
{
    int n = sizeof(cvalue);
}

في المثال أعلاه، عندما نستدعي sizeof(cvalue)، قد تتوقع أن n تساوي 8، حيث أن المصفوفة محددة بحجم 8. ومع ذلك، هذا ليس هو الحال.

المثال 2: الدالة bar()

void bar()
{
    char cvalue[8];
    int n = sizeof(cvalue);
}

في هذا المثال الثاني، sizeof(cvalue) تساوي 8. فلماذا الاختلاف؟

فهم المفهوم

لفهم لماذا ترجع sizeof(cvalue) قيمًا مختلفة في كل دالة، نحتاج إلى توضيح كيف يتم التعامل مع المصفوفات في C و C++.

المصفوفات كمعلمات دالة

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

  • void foo(char cvalue[8])
  • void foo(char cvalue[])
  • void foo(char *cvalue)

في جميع هذه التصريحات، يُفسر cvalue على أنه مؤشر. وبالتالي، عندما تستدعي sizeof(cvalue) داخل foo()، فإنها تزودك بحجم المؤشر، وليس بحجم المصفوفة. على معظم المنصات، يكون هذا الحجم عادةً 4 بايت على نظام 32-بت و 8 بايت على نظام 64-بت، وهو السبب في أن n لا تساوي 8 في foo().

السياق الصحيح في bar()

على النقيض، داخل bar()، يتم تعريف cvalue كمصفوفة محلية بحجم 8. لذلك، عندما يتم استدعاء sizeof(cvalue) هنا، فإنه يعكس بشكل صحيح حجم المصفوفة الكاملة، مما يؤدي إلى تناسب n مع 8.

النقاط الرئيسية

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

الخلاصة

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

نأمل أن يسلط هذا الشرح الضوء على سلوك عملية sizeof بالنسبة لمتغيرات المصفوفات في الدوال، موضحًا لماذا لا تتساوى n مع 8 في الدالة foo() ولكنها تتساوى في bar(). واحتفظ بهذه المبادئ في اعتبارك أثناء كتابة الشيفرة!