تیم برنامه نویسی گروه تمدن

مرجع کامل فارسی برنامه نویسی به زبان سی پلاس پلاس

  • Increase font size
  • Default font size
  • Decrease font size

آرایه، اشاره گر نیست

فرستادن به ایمیل چاپ مشاهده در قالب پی دی اف

به نام خدا

در ابتدا از خودآموز های مفید سایت شما تشکر می کنم. با توجه به احساس نیاز در این موضوع، قصد به نوشتن این مقاله در مورد اشاره گرها و آرایه ها نمودم.
متاسفانه فهم غلط بعضی موارد انسان ها را در ادامه کار دچار دردسر می کند. بنابراین درک صحیح و تمرین جهت جلوگیری از تصورات غلط بیشتر بسیار مهم است.
یک آرایه با یک اشاره گر برابر نیست. آرایه ها یک دنباله ساده از متغیرها در حافظه هستند.
زمانی که می نویسیم:

int array[3];
array[2]=666;

کامپایلر زبان C و یا ++C مقدار [array[0 را به عنوان آدرسی به یک مقدار صحیح در نظر نگرفته و آن را مستقیما به عنوان یک مقدار در نظر می گیرد. دقیقا مثل نوشته زیر:

int *ptr = new int[3];
ptr[2] = 66;

آشکارا مشخص است که var یک اشاره گر نیست؛ درست مثل [array[2

اگر به جای آرایه از اشاره گر استفاده کنیم، ظاهر برنامه ی ما مشابه زمانی است که از یک آرایه معمولی استفاده می کردیم اما برای کامپایلر این گونه نبوده و کد های اسمبلی تولید شده توسط کامپایلر برای این دو متفاوت است. برای مثال:

int *ptr = new int[3];
ptr[2] = 66;

این دو برنامه مشابه هم هستند اما معنای آن ها برای کامپایلر متفاوت است. در اولین برنامه (خط دوم)، کامپایلر برای تولید کد آن به ترتیب زیر عمل می کند.
1) از [array[0 دو خانه به سمت جلو حرکت کن و آن را برابر 666 قرار بده.
اما در برنامه ای که از اشاره گر استفاده نموده، عملکرد به صورت زیر است:
1) مقدار (آدرس) مربوط به [ptr[0 را بگیر.
2) آن را با دو جمع کن.
3) مقداری که اشاره گر به آن اشاره می کند را با 66 مقداردهی کن.
در حقیقت مقدارهای مربوط به array ، &array و [array[0 با هم برابرند. اما array& دارای نوع متفاوتی است. (آدرس حافظه مربوط  به یک آرایه را با عضو آرایه اشتباه نگیرید.)
در این قسمت جهت درک بیشتر این مقاله از مثال دیگری استفاده می کنم. من قصد نوشتن برنامه ای را دارم که یک عدد صحیح را از کاربر گرفته، آن را با 4 جمع و سپس نتیجه را چاپ می کند. این کار را یکبار با نوشتن یک اشاره گر از جنس عدد صحیح و یک بار با استفاده از مقدار عدد صحیح انجام می دهم.
با استفاده از عدد صحیح:

#include<iostream>
main(){
int int_input;
cin>>int_input;
cout<<(int_input + 4)<<endl;
return 0;
}

با استفاده از اشاره گر:

#include<iostream>
main(){
int *int_ptr = new int[1];
cin>>*int_ptr;
cout<< (*int_ptr + 4)<<endl;
delete(int_ptr);
return 0;
}

آیا واقعا کسی پیدا می شود که فکر کند این دو برنامه با هم یکسان هستند؟

بیابید نگاهی به کد اسمبلی آن ها داشته باشیم. کد اسمبلی مربوط به اولین برنامه با استفاده از عدد صحیح، به صورت زیر است:

2212: main(){
00401000 push ebp
00401001 mov ebp,esp
00401003 sub esp,44h
00401006 push ebx
00401007 push esi
00401008 push edi
2213: int int_input;
2214: cin>>int_input;
00401009 lea eax,[ebp-4]
0040100C push eax
0040100D mov ecx,offset cin (00414c58)
00401012 call istream::operator>> (0040b7c0)
2215: cout<<(int_input+4)<<endl;
00401017 push offset endl (00401070)
0040101C mov ecx,dword ptr [ebp-4]
0040101F add ecx,4
00401022 push ecx
00401023 mov ecx,offset cout (00414c18)
00401028 call ostream::operator<< (0040b3e0)
0040102D mov ecx,eax
0040102F call ostream::operator<< (00401040)
2216: return 0;
00401034 xor eax,eax
2217: }

و  کد اسمبلی برای دومین برنامه که از اشاره گر استفاده می کرد، به صورت زیر خواهد بود:

2212: main(){
00401000 push ebp
00401001 mov ebp,esp
00401003 sub esp,4Ch
00401006 push ebx
00401007 push esi
00401008 push edi
2213: int *int_ptr = new int[1];
00401009 push 4
0040100B call operator new (004011b0)
00401010 add esp,4
00401013 mov dword ptr [ebp-8],eax
00401016 mov eax,dword ptr [ebp-8]
00401019 mov dword ptr [ebp-4],eax
2214: cin>>*int_ptr;
0040101C mov ecx,dword ptr [ebp-4]
0040101F push ecx
00401020 mov ecx,offset cin (00414c38)
00401025 call istream::operator>> (0040b8a0)
2215: cout<< (*int_ptr + 4)<<endl;
0040102A push offset endl (004010a0)
0040102F mov edx,dword ptr [ebp-4]
00401032 mov eax,dword ptr [edx]
00401034 add eax,4
00401037 push eax
00401038 mov ecx,offset cout (00414bf8)
0040103D call ostream::operator<< (0040b4c0)
00401042 mov ecx,eax
00401044 call ostream::operator<< (00401070)
2216: delete(int_ptr);
00401049 mov ecx,dword ptr [ebp-4]
0040104C mov dword ptr [ebp-0Ch],ecx
0040104F mov edx,dword ptr [ebp-0Ch]
00401052 push edx
00401053 call operator delete (00401120)
00401058 add esp,4
2217: return 0;
0040105B xor eax,eax
2218: }

خط شماره 19 در برابر خط شماره 32. همان طور که می بینید، عدد صحیح با اشاره گری از جنس عدد صحیح متفاوت هستند. یک عدد صحیح مکانی از حافظه است که در آن یک عدد صحیح نگه داری می شود اما یک اشاره گر از جنس عدد صحیح (اشاره گر به عدد صحیح) مکانی از حافظه است که یک آدرس در آن ذخیره می شود. کامپایلر آدرس خانه ای از حافظه که عدد صحیح در آن نگه داری می شود را می داند. به دلیل اینکه این مقاله برای افرادی است که تازه مبادرت به برنامه نویسی کرده اند قصد توضیح کد اسمبلی آن را نداشته و بنا را بر خلاصه گویی می گذارم.

اما توضیحی در مورد اینکه که گفته شد یک آرایه، دنباله ای از متغیرها در حافظه است اما اشاره گر... . از مثال بالا نتیجه می شود که یک اشاره گر یک متغیر از نوع عدد صحیح نیست چه برسد به دنباله ای از آن ها.

منبع: سایت cplusplus.com نوشته SiavoshKC
ترجمه و ویرایش: مرجع فارسی سی پلاس پلاس به آدرس cplusplus.ir

آخرین بروز رسانی مطلب در جمعه ، 1 دی 1391 ، 12:05  

افزودن نظر

دوست عزیز و کاربر گرامی
نظرات بعد از بررسی در سایت درج خواهند شد.
مطمئنا از شنیدن انتقادهای شما خوشحال خواهیم شد.
دلیل فیلتر کردن نظرات صرفا جلوگیری از نظرات مغایر با اسلام و جمهوری اسلامی ایران می باشد. امیدواریم ما را به خاطر این کار درک نمایید. با تشکر






کد امنیتی
بازنشانی