بسم الله الرحمن الرحيم.
في هذا المقال سنتعرف على أنواع البيانات (Data Types) ومحددات التنسيق (Format Specifiers) الخاصة بها.
ملاحظة: أحياناً يجب حفظ المصطلحات الإنجليزية، لأن أغلب تعاملك مع لغات البرمجة سيكون باللغة الإنجليزية، والترجمة العربية تختلف من شخص لآخر.
ما هي أنواع البيانات؟
هي الشكل الذي تُحفظ به البيانات (كالمتغيرات) التي يمكن تخزينها ومعالجتها. أهم أنواعها:
1. الأعداد الصحيحة (Integers)
- تستخدم لتخزين الأعداد الصحيحة (1، 55، -72 — أي بدون فواصل عشرية).
- الكلمة المفتاحية:
int. - الحجم: 4 بايت في كل من x86 و x64 (انظر ملاحظة الأخطاء الشائعة أدناه).
- يمكن جعل الأعداد موجبة فقط باستخدام
unsigned.
2. الأعداد العشرية (Floating-point)
- تستخدم لتخزين الأعداد ذات الفواصل العشرية (1.2، 3.7).
float: 4 بايت.double: 8 بايت.
3. الحروف (Characters)
- تخزن محرفاً واحداً (حرف، رقم، أو أي رمز).
- الكلمة المفتاحية:
char. - الحجم: 1 بايت.
4. Void (بدون قيمة)
- يستخدم مع الدوال أو المؤشرات التي لا ترجع قيمة.
- الكلمة المفتاحية:
void. - مهم لمجال RE:
void*هو مؤشر عام (غير محدد النوع) — سنعود إليه في آخر مقالات الأساسيات لأنه من أهم الأمور في الهندسة العكسية.
جدول أحجام البيانات (على Windows x64)
| النوع | الحجم (بايت) | المدى التقريبي |
|---|---|---|
char | 1 | -128 إلى 127 |
unsigned char | 1 | 0 إلى 255 |
short | 2 | -32,768 إلى 32,767 |
int | 4 | -2.1 مليار إلى 2.1 مليار |
unsigned int | 4 | 0 إلى 4.3 مليار |
long | 4 (Windows) / 8 (Linux x64) | يعتمد على النظام |
long long | 8 | أعداد ضخمة |
float | 4 | فاصلة عشرية |
double | 8 | فاصلة عشرية بدقة أعلى |
pointer | 4 (x86) / 8 (x64) | عنوان في الذاكرة |
خطأ شائع يجب تجنبه
حجم
intلا يعتمد على المعمارية (x86/x64) — بل على المترجم/الـ ABI.intهي 4 بايت في كل من x86 و x64 على ويندوز ولينكس. أما الفارق الحقيقي بين المعماريات فيظهر في حجم المؤشرات (4 بايت في x86، 8 بايت في x64) وفيlongعلى بعض الأنظمة.
تحقق بنفسك
#include <stdio.h>
int main(void){
printf("char: %zu bytes\n", sizeof(char));
printf("int: %zu bytes\n", sizeof(int));
printf("long: %zu bytes\n", sizeof(long));
printf("ptr: %zu bytes\n", sizeof(void*));
return 0;
}
لاحظ أن
sizeof(void*)سيطبع 8 على نظام 64-bit و 4 على نظام 32-bit — هذه هي الطريقة العملية لمعرفة بنية النظام.
ما فائدة محددات التنسيق؟
تستخدم في دوال مثل printf و scanf لتنسيق إدخال أو إخراج البيانات:
printf: دالة الطباعة (إخراج البيانات).scanf: دالة القراءة (إدخال البيانات).
1. محددات الأعداد الصحيحة
| المحدد | الوصف |
|---|---|
%d | عدد صحيح موقّع (dec) |
%u | عدد صحيح غير موقّع |
%x / %X | عدد سداسي عشري (hex) — صغير/كبير |
%o | عدد ثماني |
%ld / %lld | long / long long موقّع |
%zu | size_t (المستخدم في sizeof) |
2. محددات الأعداد العشرية
| المحدد | الوصف |
|---|---|
%f | عدد عشري (float/double) |
%.1f | عدد عشري بخانة واحدة بعد الفاصلة |
%e | تمثيل علمي |
%g | تمثيل تلقائي |
3. محددات الحروف والسلاسل النصية
| المحدد | الوصف |
|---|---|
%c | حرف واحد |
%s | سلسلة نصية (string) |
%c مع %d | طباعة الحرف كرقم ASCII |
4. محددات أخرى مهمة
| المحدد | الوصف |
|---|---|
%p | مؤشر (عنوان في الذاكرة) — وليس %x |
%% | طباعة علامة % نفسها |
ربط ما تعلمناه بالهندسة العكسية
intدائماً 4 بايت: عندما ترى في الـ disassembly تعليمة تقرأ من[ebp-4]أو[rsp+8]بحجم 4 بايت، فهذا غالباً متغيرint. وهذا التطابق بين الحجم في C والأوبكود هو أول مهارة قراءة disassembly.%dمقابل%u: الأول يطبع القيمة كموقّعة والثاني كغير موقّعة. عند فك تشفير البيانات أو تحليل قيم hex، يهمك جداً هل تُفسَّر القيمة كـ signed أم unsigned — الفرق قد يقلب التحليل.charمقابلint: التعامل مع 1 بايت مقابل 4 بايتات يفسر لماذا ترى في الـ assembly تعليماتmovzx(توسيع صفري) وmovsx(توسيع بالإشارة) عند نقلcharإلىint. سنشرحها بالتفصيل في سلسلة الـ assembly.
ملاحظة ختامية
لا تقلق إذا واجهت صعوبة في حفظ محددات التنسيق — فبكثرة الاستخدام ستصبح أمراً روتينياً تلقائياً.
ملاحظة: لم نشرح هنا محدد المؤشر
%pبالتفصيل لأننا سنتطرق للمؤشرات (Pointers) في آخر مقالات الأساسيات — وهو من أهم الموضوعات المفيدة في مجال الهندسة العكسية، وفقكم الله.