usize مقابل u32: مبارزة أنواع الأعداد الصحيحة في Rust
\n\nإذا كنت تكتب بلغة Rust لمدة أسبوع على الأقل، فمن المؤكد أنك واجهت هذا الموقف: المترجم يوبخك لأنك تحاول استخدام u32 لفهرسة مصفوفة، بينما هو يتطلب usize. أو العكس — تمرر usize إلى دالة تنتظر u32، وتحصل على موجة حمراء في بيئة التطوير.
على Stack Overflow، سؤال «ما الفرق بين usize و u32؟» حصد آلاف المشاهدات. هذا ليس من قبيل الصدفة — فالخلط بين هذين النوعين هو أحد أكثر الفخاخ شيوعًا للمبتدئين في Rust.
دعنا ننهي هذا الأمر مرة واحدة وإلى الأبد: ما الفرق بينهما، ومتى تستخدم أيًا منهما، وكيف تتجنب الوقوع في المشاكل. هيا بنا!
\n\nباختصار: الفرق الرئيسي
\n\nusize هو عدد صحيح غير موقع، حجمه يعتمد على بنية النظام. على نظام 64 بت، حجمه 8 بايت، وعلى نظام 32 بت، حجمه 4 بايت. u32 هو دائمًا 4 بايت، بغض النظر عن المنصة.
لكن الفرق ليس فقط في الحجم. الفرق الرئيسي هو الدلالة:
\n\n- \n
usize— لـ الأحجام، الفهارس، وعدد العناصر في المجموعات \n u32— لـ البيانات الرقمية التي لا تتجاوز 4 مليارات \n
ونعم، المترجم لا يسمح بخلطهما دون تحويل صريح. هذا ليس خطأ، بل ميزة — بهذه الطريقة تحميك Rust من الأخطاء المتعلقة بعرض البت في البنية.
\n\nلماذا يوجد usize؟
\n\nتخيل أنك تكتب كودًا يجب أن يعمل على متحكم دقيق قديم 32 بت وعلى خادم حديث 64 بت. طول المصفوفة على نظام 32 بت لا يمكن أن يتجاوز 2^32 - 1 عنصرًا، بينما على نظام 64 بت يمكن أن يصل إلى 2^64 - 1.
إذا كنت تستخدم u32 للفهرسة على نظام 64 بت، فلن تتمكن ببساطة من الوصول إلى العناصر التي تتجاوز 4 مليارات — حتى لو كانت الذاكرة كافية. usize يحل هذه المشكلة: فهو دائمًا يسع أكبر حجم ممكن للذاكرة على البنية الحالية.
// مثال: usize يتكيف تلقائيًا مع البنية\nfn main() {\n let large_vec: Vec<u8> = vec![0; 1_000_000_000]; // مليار عنصر\n \n // usize يسع هذا الفهرس على أي منصة\n let index: usize = 999_999_999;\n println!("العنصر: {}", large_vec[index]);\n \n // لكن u32 قد لا يكفي على نظام 32 بت\n // let bad_index: u32 = 999_999_999; // على نظام 32 بت، سيتم تجميعه، لكن...\n // large_vec[bad_index as usize]; // ...سيتعين عليك إجراء تحويل\n}\n\nمقارنة في جدول
\n\n| الخاصية | \nusize | \nu32 | \n
|---|---|---|
| الحجم على 64-bit | \n8 بايت | \n4 بايت | \n
| الحجم على 32-bit | \n4 بايت | \n4 بايت | \n
| النطاق (64-bit) | \n0 .. 2^64-1 | \n0 .. 2^32-1 | \n
| الاستخدام الأساسي | \nالفهارس، الأحجام، الأطوال | \nالبيانات الرقمية | \n
| التحويل الضمني | \nلا | \nلا | \n
متى تستخدم usize؟
\n\nدائمًا لفهرسة المجموعات. هذه قاعدة لا استثناءات فيها تقريبًا. إذا كتبت vec[i] حيث i من نوع u32، سيقول المترجم: «يا صديقي، استخدم usize من فضلك».
// صحيح: استخدام usize للفهارس\nfn get_element(vec: &[i32], index: usize) -> Option<&i32> {\n vec.get(index)\n}\n\n// غير صحيح: استخدام u32 للفهرسة — سيتعين التحويل\nfn get_ele