سؤال

لقد لاحظت أنه يبدو أن كود C و C++ الحديث يستخدم size_t بدلاً من int/unsigned int إلى حد كبير في كل مكان - من معلمات وظائف سلسلة C إلى STL.أشعر بالفضول لمعرفة سبب ذلك والفوائد التي يجلبها.

هل كانت مفيدة؟

المحلول

ال size_t النوع هو نوع عدد صحيح غير موقع وهو نتيجة sizeof المشغل (و offsetof عامل التشغيل)، لذا فمن المؤكد أن تكون كبيرة بما يكفي لاحتواء حجم أكبر كائن يمكن لنظامك التعامل معه (على سبيل المثال، مصفوفة ثابتة تبلغ سعتها 8 جيجا بايت).

ال size_t قد يكون النوع أكبر من أو يساوي أو أصغر من unsigned int, ، وقد يضع المترجم الخاص بك افتراضات حول هذا الموضوع من أجل التحسين.

قد تجد معلومات أكثر دقة في معيار C99، القسم 7.17، والذي تتوفر مسودة منه على الإنترنت في بي دي إف التنسيق، أو في معيار C11، القسم 7.19، وهو متاح أيضًا كملف مشروع قوات الدفاع الشعبي.

نصائح أخرى

Classic C (اللهجة المبكرة لـ C التي وصفها بريان كيرنيغان ودينيس ريتشي في لغة البرمجة C، برنتيس هول، 1978) لم توفر size_t.قدمت لجنة معايير C size_t للقضاء على مشكلة قابلية النقل

تم شرحه بالتفصيل على موقع Embed.com (مع مثال جيد جدًا)

باختصار، size_t لا يكون سلبيًا أبدًا، ويعمل على زيادة الأداء لأنه من المفترض أن يكون من النوع الصحيح غير الموقع الذي يكون كبيرًا بما يكفي - ولكن ليس كبيرًا جدًا - لتمثيل حجم أكبر كائن ممكن على النظام الأساسي المستهدف.

لا ينبغي أبدا أن تكون الأحجام سلبية، وبالفعل size_t هو نوع غير موقعة.أيضا، لأن size_t غير مُوقع، يمكنك تخزين أرقام يبلغ حجمها تقريبًا ضعف حجم النوع المُوقع المقابل، لأنه يمكننا استخدام بت الإشارة لتمثيل الحجم، مثل جميع البتات الأخرى في العدد الصحيح غير المُوقع.وعندما نكتسب بتة أخرى، فإننا نضرب نطاق الأعداد التي يمكننا تمثيلها في عامل يساوي اثنين تقريبًا.

لذلك، تسأل، لماذا لا تستخدم فقط unsigned int؟قد لا يكون قادرًا على الاحتفاظ بأعداد كبيرة بما يكفي.في التنفيذ حيث unsigned int هو 32 بت، أكبر رقم يمكن أن يمثله هو 4294967295.يمكن لبعض المعالجات، مثل IP16L32، نسخ كائنات أكبر من 4294967295 بايت.

لذلك، تسأل، لماذا لا تستخدم unsigned long int؟إنه يفرض ضريبة على الأداء على بعض المنصات.يتطلب المعيار C أن أ long تشغل 32 بت على الأقل.تنفذ منصة IP16L32 كل كلمة بطول 32 بت كزوج من الكلمات بطول 16 بت.تتطلب جميع مشغلات 32 بت تقريبًا على هذه الأنظمة الأساسية تعليمتين، إن لم يكن أكثر، لأنها تعمل مع 32 بت في قطعتين 16 بت.على سبيل المثال، عادةً ما يتطلب نقل مقطع بطول 32 بت تعليماتين للآلة - واحدة لنقل كل مقطع بطول 16 بت.

استخدام size_t يتجنب حصيلة الأداء هذه.وفق هذه المقالة الرائعة, ، "يكتب size_t هو typedef وهو اسم مستعار لبعض أنواع الأعداد الصحيحة غير الموقعة، عادةً unsigned int أو unsigned long, ، ولكن ربما حتى unsigned long long.من المفترض أن يختار كل تطبيق لمعيار C عددًا صحيحًا غير موقّع كبيرًا بما يكفي - ولكن ليس أكبر من المطلوب - لتمثيل حجم أكبر كائن ممكن على النظام الأساسي المستهدف.

نوع size_t هو النوع الذي يتم إرجاعه بواسطة عامل التشغيل sizeof.وهو عدد صحيح غير موقّع قادر على التعبير عن الحجم بالبايت لأي نطاق ذاكرة مدعوم على الجهاز المضيف.وهي (عادةً) مرتبطة بـ ptrdiff_t حيث أن ptrdiff_t عبارة عن قيمة عددية موقعة بحيث يكون sizeof(ptrdiff_t) وsizeof(size_t) متساويين.

عند كتابة كود C يجب عليك دائماً استخدم size_t عند التعامل مع نطاقات الذاكرة.

من ناحية أخرى، يتم تعريف نوع int بشكل أساسي على أنه حجم قيمة العدد الصحيح (الموقّع) التي يمكن للجهاز المضيف استخدامها لإجراء العمليات الحسابية الصحيحة بشكل أكثر كفاءة.على سبيل المثال، في العديد من أجهزة الكمبيوتر القديمة من نوع PC، ستكون قيمة sizeof(size_t) 4 (بايت) ولكن sizeof(int) ستكون 2 (بايت).كان حساب 16 بت أسرع من حساب 32 بت، على الرغم من أن وحدة المعالجة المركزية يمكنها التعامل مع مساحة ذاكرة (منطقية) تصل إلى 4 جيجا بايت.

استخدم النوع int فقط عندما تهتم بالكفاءة لأن دقته الفعلية تعتمد بقوة على كل من خيارات المترجم وهندسة الآلة.على وجه الخصوص، يحدد معيار C الثوابت التالية:sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) لا يضع أي قيود أخرى على التمثيل الفعلي للدقة المتاحة للمبرمج لكل من هذه الأنواع البدائية.

ملحوظة:هذا ليس هو نفسه كما هو الحال في Java (الذي يحدد في الواقع دقة البت لكل نوع من الأنواع "char" و"byte" و"short" و"int" و"long").

يجب أن يكون النوع size_t كبيرًا بما يكفي لتخزين حجم أي كائن محتمل.ليس من الضروري أن يستوفي int غير الموقع هذا الشرط.

على سبيل المثال، في أنظمة 64 بت، قد يكون عرض int وunsigned int 32 بت، ولكن يجب أن يكون size_t كبيرًا بما يكفي لتخزين أرقام أكبر من 4G

قد يكون هذا المقتطف من دليل glibc 0.02 ذا صلة أيضًا عند البحث في الموضوع:

هناك مشكلة محتملة في نوع size_t وإصدارات دول مجلس التعاون الخليجي قبل الإصدار 2.4.يتطلب ANSI C أن يكون size_t دائمًا من النوع غير الموقع.للتوافق مع ملفات رأس الأنظمة الموجودة، يحدد مجلس التعاون الخليجي size_t in stddef.h' to be whatever type the system'sيحدده sys/types.h.معظم أنظمة Unix التي تحدد size_t في `sys/types.h'، تحدده على أنه نوع موقّع.تعتمد بعض التعليمات البرمجية الموجودة في المكتبة على كون size_t نوعًا غير موقّع، ولن تعمل بشكل صحيح إذا تم توقيعها.

رمز مكتبة GNU C الذي يتوقع أن يكون size_t غير موقّع صحيح.تعريف size_t كنوع موقّع غير صحيح.نحن نخطط أنه في الإصدار 2.4، سيحدد مجلس التعاون الخليجي دائمًا size_t كنوع غير موقّع، وسيقوم ملف fixincludes' script will massage the system'ssys/types.h" حتى لا تتعارض مع هذا.

في غضون ذلك، نعمل على حل هذه المشكلة عن طريق إخبار مجلس التعاون الخليجي بشكل صريح باستخدام نوع غير موقّع لـ size_t عند تجميع مكتبة GNU C.سيكتشف "التكوين" تلقائيًا النوع الذي يستخدمه مجلس التعاون الخليجي لـ size_t لترتيب تجاوزه إذا لزم الأمر.

إذا تم تعيين المترجم الخاص بي على 32 بت، size_t ليس سوى typedef ل unsigned int.إذا تم تعيين المترجم الخاص بي على 64 بت، size_t ليس سوى typedef ل unsigned long long.

size_t هو حجم المؤشر.

لذلك في 32 بت أو نموذج ILP32 الشائع (عدد صحيح، طويل، مؤشر) size_t هو 32 بت.وفي 64 بت أو نموذج LP64 (الطويل والمؤشر) الشائع size_t هو 64 بت (الأعداد الصحيحة لا تزال 32 بت).

هناك نماذج أخرى ولكن هذه هي النماذج التي يستخدمها g++ (على الأقل افتراضيًا)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top