Menu
flag Ar iconالعربيةdown icon

أنواع البيانات في C++: int وdouble وchar وbool والمزيد

جولة عملية في أنواع البيانات الأساسية في C++ - الأعداد الصحيحة والفاصلة العائمة وchar وbool - بالإضافة إلى الأحجام، وsigned مقابل unsigned، والقيم الحرفية واللواحق، والفيض، وكيفية اختيار النوع المناسب.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

لماذا تهمّ الأنواع في C++

في صفحة المتغيرات أعلنت قيمًا بنوع صريح مثل int age = 30;. هذا النوع ليس مجرد لافتة - فهو يخبر المترجم بعدد البايتات التي يحجزها، وكيف يفسّر تلك البايتات، وأي العمليات مسموح بها. وإذا أخطأت في النوع فقد تفقد الدقّة بصمت، أو تتعرّض للفيض، أو تستدعي سلوكًا غير معرّف.

تجمّع C++ أنواعها المدمجة في عدة عائلات: الأعداد الصحيحة، وأعداد الفاصلة العائمة، ونوع المحرف، والنوع المنطقي. لننظر إلى كل واحد منها، ثم إلى القواعد التي يتعثّر فيها الناس.

الأنواع الأساسية

إليك مثالًا واحدًا لكل نوع جوهري في برنامج واحد. لاحظ لواحق القيم الحرفية (L وf وu) وعلامتي الاقتباس المفردتين حول char:

يُطبع bool افتراضيًا كـ 1 أو 0، وليس true/false. ويستخدم char علامتي اقتباس مفردتين - فـ 'A' محرف واحد، بينما "A" (علامتا اقتباس مزدوجتان) قيمة حرفية نصية، وهي نوع مختلف تمامًا. وهذان الخطآن شائعان للغاية في البداية.

الأحجام ليست ثابتة

هذه أكبر مفاجأة لمن يأتي من لغات مثل Java. لا يضمن معيار C++ سوى الأحجام الدنيا وترتيب نسبي (shortintlonglong long). أما الحجم الفعلي فيعتمد على المترجم والمنصة لديك. تحقّق دائمًا بـ sizeof:

في بناء Linux نموذجي بـ 64 بت سترى int = 4 وlong = 8. أما على ويندوز بـ 64 بت فإن long يبلغ 4 بايتات فقط. هذه الفجوة في قابلية النقل هي بالضبط السبب الذي يجعلك لا تكتب شيفرة تفترض أن long بحجم 64 بت.

عندما تحتاج إلى عرض دقيق، الجأ إلى أنواع الأعداد الصحيحة ذات العرض الثابت في <cstdint>:

استخدم int32_t/int64_t لصيغ الملفات وبروتوكولات الشبكة أو أي شيء يجب أن يتصرّف بشكل متطابق عبر الأجهزة. لاحظ التحويل (int)a - فبثّ نوع بحجم 8 بت يطبعه كمحرف لا كرقم، لذا حوّله أولًا.

Signed مقابل unsigned

يأتي كل نوع صحيح في صنفين. يمكن للنوع signed أن يحمل قيمًا سالبة؛ أما النوع unsigned فلا يستطيع، مقايضًا المدى السالب بقيمة موجبة قصوى أعلى. والنوع int العادي signed افتراضيًا.

الطرح من 0 غير المُوقَّع يلتفّ إلى عدد موجب هائل بدلًا من أن يصبح سالبًا. وهذا يوقع الناس باستمرار - وبخاصة مع size_t (وهو نوع unsigned) الذي تُعيده .size():

vector<int> v = {1, 2, 3};
// خطر: v.size() من نوع unsigned. إذا كانت v فارغة، فإن v.size() - 1 يلتفّ
// إلى عدد ضخم وتعمل الحلقة إلى ما لا نهاية تقريبًا.
for (size_t i = 0; i <= v.size() - 1; i++) { /* ... */ }

فضّل i < v.size() (لا تستخدم أبدًا <= size() - 1)، أو تجنّب المشكلة كلها عبر حلقة for قائمة على نطاق.

فيض الأعداد الصحيحة سلوك غير معرّف

على عكس التفاف الأنواع unsigned (وهو معرّف جيدًا)، فإن فيض الأعداد الصحيحة المُوقَّعة سلوك غير معرّف في C++. ويُسمح للمترجم بفعل أي شيء - إعادة قيمة عشوائية، أو حذف الفحص أثناء التحسين، أو الانهيار:

الحل هو نفسه فخّ الفيض في أي لغة: أجرِ العملية الحسابية في نوع أعرض. حوّل أحد المعاملين إلى long long قبل علامة +، حتى يجري الجمع بـ 64 بت. وتحويل الناتج بعد ذلك يأتي متأخرًا جدًا - فالفيض قد حدث بالفعل.

اختيار النوع المناسب

في معظم الشيفرات تفي القيم الافتراضية بالغرض: int للأعداد الصحيحة، وdouble للأعداد العشرية. والجأ إلى غيرها فقط عندما يكون لديك سبب.

النوعالحجم المعتاداستخدمه عند
int32 بتالافتراضي للأعداد الصحيحة
long long64 بتالقيم التي تتجاوز ~2 مليار: الطوابع الزمنية، العدّادات الكبيرة
double64 بتالافتراضي للأعداد العشرية - دقة جيدة
float32 بتالمصفوفات الضيقة بالذاكرة حيث يمكن التضحية بالدقة
bool1 بايتراية true/false
int32_t / int64_tدقيقالصيغ العابرة للمنصات، البروتوكولات، التلاعب بالبتات

بعض المزالق التي ينبغي تذكّرها. لا يملك float سوى نحو 7 أرقام عشرية معنوية، لذا فإن 0.1f + 0.2f ليس 0.3 بالضبط - ففضّل double ما لم تكن بحاجة فعلية إلى توفير الذاكرة. كما أن char قد يكون signed أو unsigned تبعًا للمنصة، لذا إذا أجريت عمليات حسابية على بايتات خام، فاكتب صراحةً signed char أو unsigned char.

التالي: الكلمة المفتاحية auto

كتابة النوع في كل مرة تصبح مملّة، وأحيانًا يكون النوع طويلًا أو صعب التسمية. تتيح C++ للمترجم استنتاجه نيابةً عنك عبر الكلمة المفتاحية auto - فـ auto x = 42; يجعل x من نوع int، وauto it = v.begin(); يوفّر عليك كتابة نوع مكرّر مُطوَّل. وتتناول الصفحة التالية متى يجعل auto الشيفرة أوضح ومتى يخفي أكثر من اللازم.

الأسئلة الشائعة

ما هي أنواع البيانات الأساسية في C++؟

الأنواع الأساسية هي الأعداد الصحيحة (short وint وlong وlong long)، والفاصلة العائمة (float وdouble وlong double)، ونوع المحرف char، والنوع المنطقي bool. ويمكن لكل نوع صحيح أن يكون أيضًا signed أو unsigned. وكل ما عداها - std::string والمصفوفات وأصنافك الخاصة - مبني فوق هذه الأنواع.

ما الفرق بين int وlong في C++؟

كلاهما يخزّن أعدادًا صحيحة، لكن يُضمَن أن يكون long بعرض لا يقل عن int (غالبًا 64 بت على المنصات ذات 64 بت، لكنه 32 بت فقط على ويندوز). يحدّد المعيار الأحجام الدنيا فقط، لذا للحصول على عرض مضمون استخدم الأنواع ذات العرض الثابت من <cstdint> مثل int32_t وint64_t.

ما حجم int في C++؟

يضمن المعيار أن يكون int بحجم لا يقل عن 16 بت فقط، لكنه في كل حاسوب مكتبي وخادم حديث تقريبًا يبلغ 32 بت. وبما أن الأحجام تعتمد على المنصة، لا تفترض أبدًا - اطبع sizeof(int) للتحقق، أو استخدم أنواع <cstdint> مثل int32_t عندما تحتاج إلى عرض دقيق.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن