آرایه اشاره گر نیست
در ابتدا از خودآموز های مفید سایت شما تشکر می کنم. با توجه به احساس نیاز در این موضوع، قصد به نوشتن این مقاله در مورد اشاره گرها و آرایه ها نمودم.
متاسفانه فهم غلط بعضی موارد انسان ها را در ادامه کار دچار دردسر می کند. بنابراین درک صحیح و تمرین جهت جلوگیری از تصورات غلط بیشتر بسیار مهم است.
یک آرایه با یک اشاره گر برابر نیست. آرایه ها یک دنباله ساده از متغیرها در حافظه هستند.
زمانی که می نویسیم:
int array[3];
array[2]=666;
کامپایلر زبان C و یا ++C مقدار [array[0 را به عنوان آدرسی به یک مقدار صحیح در نظر نگرفته و آن را مستقیما به عنوان یک مقدار در نظر می گیرد. دقیقا مثل نوشته زیر:
int *ptr = new int[۳];
ptr[2] = 66;
آشکارا مشخص است که var یک اشاره گر نیست؛ درست مثل [array[2
اگر به جای آرایه از اشاره گر استفاده کنیم، ظاهر برنامه ی ما مشابه زمانی است که از یک آرایه معمولی استفاده می کردیم اما برای کامپایلر این گونه نبوده و کد های اسمبلی تولید شده توسط کامپایلر برای این دو متفاوت است. برای مثال:
int *ptr = new int[۳];
ptr[2] = 66;
این دو برنامه مشابه هم هستند اما معنای آن ها برای کامپایلر متفاوت است. در اولین برنامه (خط دوم)، کامپایلر برای تولید کد آن به ترتیب زیر عمل می کند.
1) از [array[0 دو خانه به سمت جلو حرکت کن و آن را برابر ۶۶۶ قرار بده.
اما در برنامه ای که از اشاره گر استفاده نموده، عملکرد به صورت زیر است:
1) مقدار (آدرس) مربوط به [ptr[0 را بگیر.
2) آن را با دو جمع کن.
3) مقداری که اشاره گر به آن اشاره می کند را با ۶۶ مقداردهی کن.
در حقیقت مقدارهای مربوط به array ، &array و [array[0 با هم برابرند. اما array& دارای نوع متفاوتی است. (آدرس حافظه مربوط به یک آرایه را با عضو آرایه اشتباه نگیرید.)
در این قسمت جهت درک بیشتر این مقاله از مثال دیگری استفاده می کنم. من قصد نوشتن برنامه ای را دارم که یک عدد صحیح را از کاربر گرفته، آن را با ۴ جمع و سپس نتیجه را چاپ می کند. این کار را یکبار با نوشتن یک اشاره گر از جنس عدد صحیح و یک بار با استفاده از مقدار عدد صحیح انجام می دهم.
با استفاده از عدد صحیح:
#include<iostream>
main(){
int int_input;
cin>>int_input;
cout<<(int_input + 4)<<endl;
return 0;
}
با استفاده از اشاره گر:
#include<iostream>
main(){
int *int_ptr = new int[۱];
cin>>*int_ptr;
cout<< (*int_ptr + 4)<<endl;
delete(int_ptr);
return 0;
}
آیا واقعا کسی پیدا می شود که فکر کند این دو برنامه با هم یکسان هستند؟
بیابید نگاهی به کد اسمبلی آن ها داشته باشیم. کد اسمبلی مربوط به اولین برنامه با استفاده از عدد صحیح، به صورت زیر است:
۲۲۱۲: main(){
۰۰۴۰۱۰۰۰ push ebp
۰۰۴۰۱۰۰۱ mov ebp,esp
۰۰۴۰۱۰۰۳ sub esp,44h
۰۰۴۰۱۰۰۶ push ebx
۰۰۴۰۱۰۰۷ push esi
۰۰۴۰۱۰۰۸ push edi
۲۲۱۳: int int_input;
۲۲۱۴: cin>>int_input;
۰۰۴۰۱۰۰۹ lea eax,[ebp-4]
0040100C push eax
0040100D mov ecx,offset cin (00414c58)
۰۰۴۰۱۰۱۲ call istream::operator>> (0040b7c0)
۲۲۱۵: cout<<(int_input+4)<<endl;
۰۰۴۰۱۰۱۷ push offset endl (00401070)
0040101C mov ecx,dword ptr [ebp-4]
0040101F add ecx,4
۰۰۴۰۱۰۲۲ push ecx
۰۰۴۰۱۰۲۳ mov ecx,offset cout (00414c18)
۰۰۴۰۱۰۲۸ call ostream::operator<< (0040b3e0)
0040102D mov ecx,eax
0040102F call ostream::operator<< (00401040)
۲۲۱۶: return 0;
۰۰۴۰۱۰۳۴ xor eax,eax
۲۲۱۷: }
و کد اسمبلی برای دومین برنامه که از اشاره گر استفاده می کرد، به صورت زیر خواهد بود:
۲۲۱۲: main(){
۰۰۴۰۱۰۰۰ push ebp
۰۰۴۰۱۰۰۱ mov ebp,esp
۰۰۴۰۱۰۰۳ sub esp,4Ch
۰۰۴۰۱۰۰۶ push ebx
۰۰۴۰۱۰۰۷ push esi
۰۰۴۰۱۰۰۸ push edi
۲۲۱۳: int *int_ptr = new int[۱];
۰۰۴۰۱۰۰۹ push 4
0040100B call operator new (004011b0)
۰۰۴۰۱۰۱۰ add esp,4
۰۰۴۰۱۰۱۳ mov dword ptr [ebp-8],eax
۰۰۴۰۱۰۱۶ mov eax,dword ptr [ebp-8]
۰۰۴۰۱۰۱۹ mov dword ptr [ebp-4],eax
۲۲۱۴: cin>>*int_ptr;
0040101C mov ecx,dword ptr [ebp-4]
0040101F push ecx
۰۰۴۰۱۰۲۰ mov ecx,offset cin (00414c38)
۰۰۴۰۱۰۲۵ call istream::operator>> (0040b8a0)
۲۲۱۵: cout<< (*int_ptr + 4)<<endl;
0040102A push offset endl (004010a0)
0040102F mov edx,dword ptr [ebp-4]
۰۰۴۰۱۰۳۲ mov eax,dword ptr [edx]
۰۰۴۰۱۰۳۴ add eax,4
۰۰۴۰۱۰۳۷ push eax
۰۰۴۰۱۰۳۸ mov ecx,offset cout (00414bf8)
0040103D call ostream::operator<< (0040b4c0)
۰۰۴۰۱۰۴۲ mov ecx,eax
۰۰۴۰۱۰۴۴ call ostream::operator<< (00401070)
۲۲۱۶: delete(int_ptr);
۰۰۴۰۱۰۴۹ mov ecx,dword ptr [ebp-4]
0040104C mov dword ptr [ebp-0Ch],ecx
0040104F mov edx,dword ptr [ebp-0Ch]
۰۰۴۰۱۰۵۲ push edx
۰۰۴۰۱۰۵۳ call operator delete (۰۰۴۰۱۱۲۰)
۰۰۴۰۱۰۵۸ add esp,4
۲۲۱۷: return 0;
0040105B xor eax,eax
۲۲۱۸: }
خط شماره ۱۹ در برابر خط شماره ۳۲. همان طور که می بینید، عدد صحیح با اشاره گری از جنس عدد صحیح متفاوت هستند. یک عدد صحیح مکانی از حافظه است که در آن یک عدد صحیح نگه داری می شود اما یک اشاره گر از جنس عدد صحیح (اشاره گر به عدد صحیح) مکانی از حافظه است که یک آدرس در آن ذخیره می شود. کامپایلر آدرس خانه ای از حافظه که عدد صحیح در آن نگه داری می شود را می داند. به دلیل اینکه این مقاله برای افرادی است که تازه مبادرت به برنامه نویسی کرده اند قصد توضیح کد اسمبلی آن را نداشته و بنا را بر خلاصه گویی می گذارم.
اما توضیحی در مورد اینکه که گفته شد یک آرایه، دنباله ای از متغیرها در حافظه است اما اشاره گر… . از مثال بالا نتیجه می شود که یک اشاره گر یک متغیر از نوع عدد صحیح نیست چه برسد به دنباله ای از آن ها.
منبع: سایت cplusplus.com نوشته SiavoshKC
ترجمه و ویرایش: مرجع فارسی سی پلاس پلاس به آدرس cplusplus.ir
نویسنده: تمدن
لازم به ذکر است که دامنه cplusplus.ir توسط من تهیه شده و در حال حاضر محتوای سایت را روی وبلاگ بارگذاری کرده ام ;)
برای مشاهدۀ فهرست مطالب به آدرس tamadon.net/cpp مراجعه فرمایید.
دیدگاه خود را ثبت کنید
تمایل دارید در گفتگو شرکت کنید؟نظری بدهید!