الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

سؤال حول ال String literals في السي

مغلق
بدأه mhewedy في 12 أغسطس 2010 · 5 رد · 521 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم...

لي سؤال حول مايسمي ال String literals أو constants في السي:

شاهد هذه المثال و الناتج الخاص به:

//java_like_string_init.c
#include <stdio.h>

int main(void)
{
	char arr[] = "ABC";
	printf("%p %p\n", arr, "ABC");

	char *arr_ptr = "XYZ";
	printf("%p %p\n", arr_ptr, "XYZ");

	return 0;
}
//result:
//0022FF74 00403000
//0040300B 0040300B

1- بالنسبة عند إنشاء String من char ptr ...

هل يعني هذا أنه تم إنشاء char* يحتوي على "XYZ" بواسطة المترجم و تم حفظه في مكان ما ومن ثم تم إسناد عنوانه للمتغير arr_ptr و بذلك عندما نطلب "XYZ" فنحن نقصد ال char* المحفوظ مع المترجم؟

2- لماذا لم تعمل الميكانيكيه الموجوده في رقم 1 إن صحت مع ال char[] ؟؟

1
#2

وعليكم السلام .

1- يقوم المترجم بوضع النص في مكان ما بأحد قطاعات الـBinary (قسم الـData مثلا) ، ثم بقوم باسناد عنوان النص الى المؤشر arr_ptr .


push ebp
mov ebp,esp
sub esp,8
mov eax,dword ptr [004020f4] ; "ABC"
mov dword ptr [ebp-4],eax ; arr
push offset 004020f8 ; "ABC"
lea ecx,[ebp-4] ; arr
push ecx
push offset 004020fc ; "%p %p\n"
call dword ptr [printf (004020a0)]
add esp,0Ch
mov dword ptr [ebp-8],offset 00402104 ; arr_ptr(1); "XYZ"(2)
push offset 00402108 ; "XYZ"
mov edx,dword ptr [ebp-8] ; arr_ptr
push edx
push offset 0040210c ; "%p %p\n"
call dword ptr [printf (004020a0)]
add esp,0Ch
xor eax,eax
mov esp,ebp
pop ebp
ret

2- في هذه الحالة يتم حجز مساحة من الـstack ثم يتم نسخ النص اليها ، النص نفسه اما ان يكون موجود في احد اقسام الـbinary ويتم نسخه الى الـlocal variable او يتم ملئ الـlocal variable النص مباشرة داخل الـدالة .

النصوص المتشابهة اذا تكررت في نفس الـbinary يمكن ان تختزل في مكان واحد حسب خيارات الـCompiler (بالتحديد الـString pooling) .

4

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#3

بالنسبه للتعريف الأول و هو:

 char arr[] = "ABC";

هنا انت تجعل المترجم يقوم بإنشاء ثابت نصي بالقيمه "ABC\0" داخل مكان ما بالذاكره يليها حجز مساحه داخل الـ stack بقدر 4 بايت و يتم نسخ إليها هذا النص و بالتالي انت تستطيع تغيير محتوى المصفوفه كما تريد حيث ان ما بها هو نسخه من الموجود داخل الذاكره التى تحتوى على النص "ABC\0".

بالنسبه للتعريف الثانى و هو:

char *arr_ptr = "XYZ";

انت هنا تجعل المترجم يقوم بإنشاء ثابت نصي بالقيمه "XYZ\0" و من ثم يأخذ عنوان هذا الموقع و يضعه داخل المتغير arr_ptr و في هذه الحاله المتغير arr_ptr هو مؤشر لثابت و تعريفه ضمنيا هو كالتالى:

char const* arr_ptr = "XYZ";

حيث انك لا تستطيع تغيير ما يشير إليه و لكنك تستطيع تغيير قيمة المؤشر ذاتها.

نقطه اخرى النصوص المتشابهه بشكل افتراضى لا يتم حجز مساحه لها فى الذاكره مرتين حيث يكون لها عنوان واحد فقط و يمكنك تجربة الكود التالى للتأكد من هذا الكلام:

int main()
{
	char* str = "Test String.";

	printf("%p %p\n", str, "Test String.");
}

بعض المترجمات تسمح بوجود اكثر من نسخه من نفس النص داخل اكثر من مكان بالذاكره.

هذا السؤال مكرر.

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 13 أغسطس 2010 في 15:32

3

مدونتي: C++ Tips and Tricks

#4

سبقتنى يا G.

مدونتي: C++ Tips and Tricks

#5
tongue.gif

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#6

متشكر جدا.... جزاكما الله كل الخير... الأن وضحت الرؤيه......

حقيقة يبدوا أني أحتاج لفهم ولو بسيط للأسمبلي ... ربما أجد فرصه للتعرف عليه قريبا :D

1

هذا الموضوع مغلق.

مواضيع مشابهة