اشاره گر چیست؟
اشاره گرها از مهمترین قابلیتهای ++C هستند.
اشاره گر که معادل فارسی لغت pointer(پوینتر)است همان طور که از نامش پیداست قرار است که اشاره کند!
به کجا؟ به یک آدرس حافظه.کدام حافظه؟ حافظه ی RAM
اشاره گر به چه درد می خورد؟
متغیرها چیزی نیستند جز خانه هایی از حافظه. RAM مثلا وقتی یک متغیر از نوع عدد صحیح یا int تعریف می کنیم، در زمان اجرای برنامه بخشی از حافظه ی RAM که متعلق به برنامه ی دیگر و متغیر دیگری نیست (آزاد است) به این عدد تخصیص می یابد. در این حالت که متغیر ما int است، 4 بایت از حافظه به این متغیر تخصیص داده می شود (چرا؟)
هر خانه ی حافظه، آدرس منحصر به فردی دارد که در سیستم های 32 بیتی یک مقدار 32بیتی یا 4بایتی مثل 0x003245100 است(در مبنای هگز هر دو رقم بیانگر یک بایت است). در سیستمهای 64 بیتی آدرسها 64 بیتی اند یعنی چیزی شبیه به 0x0000000003245100. خوب حالا اشاره گر، چیزی! است که می تواند آدرس یک متغیر از هر نوعی را در خود نگه دارد.
اگر یک اشاره گر داشته باشیم، در واقع به آدرسهای مختلف حافظه (تا جایی که مجاز هستیم) می توانیم دسترسی پیدا کنیم. مهمترین استفاده اشاره گرها هم در کار با حافظه است، مخصوصا زمانی که قصد داریم حافظه ی زیادی تخصیص دهیم یا مرتبا حافظه بگیریم و آزاد کنیم. لیکن قبل از اینکه بیشتر شلوغش کنیم بهتره نحوه تعریف یک اشاره گر را ببینیم.
علامتهای & و * :
علامت & : این علامت آدرس یک متغیر در حافظه RAM را بر می گرداند که همواره یک عدد شانزده دهیست.
int main()
{
int n=12;
cout<<&n<<endl;
{
علامت* :این علامت بر ضد علامت & عمل می کند یعنی اگر آدرس حافظه را به ان بدهیم خود مقدار موجود در ان نقطه از حافظه را بر می گرداند.
int main()
{
int n=12;
cout<<*&n<<endl;
}
ارجاع و آدرس متغیر:
ارجاع :ارجاع در واقع یک نام مستعار برای یک متغیر است و خود یک متغیر جداگانه نیست به عبارت دیگر با تغییر متغیر اصلی ارجاع نیز تغییر می کند و همچنین با تغییر ارجاع متغیر اصلی هم تغییر می کند.
برای تعریف ارجاع بصورت زیر عمل می کنیم :
int n=44;
int &pn=n;
که در ان pn یک ارجاع است
تذکر مهم:علامت & که برای نشان دادن آدرس متغیر استفاده می شود با علامت & که در تعریف متغیراز نوع ارجاع استفاده می شود هیچ رابطه ای ندارد.
ذخیره آدرس متغیر:
بعضی مواقع لازم می شود که آدرس متغیر را در جایی ذخیره کنیم ولی آدرس متغیر یک عدد معمولی نیست و بصورت اعداد شانزده دهی نوشته می شود برای تعریف این نوع متغیر که آدرس را در خود نگه دارد بصورت زیر عمل می کنیم
int n=44;
int *pn=&n;
تذکر مهم: علامت * که برای نشان دادن محتویات آدرسهاو همچنین قرار دادن مقدار در ان آدرسها (بعدا توضیح داده می شود) استفاده می شود با علامت * که در تعریف بالا استفاده شد هیچ رابطه ای ندارد.
اشاره به اشارگر دیگر:
برای اشاره از یک اشاره گر به اشاره گر دیگر در هر مرحله یک * اضافه می کنیم مثلا اگر داشته باشیم :
int n=44;
int* pn=&n;
انگاه برای اشاره به pn& یک * زیاد می کنیم مثلا:
int **ppn=&pn;
یعنی نمی توانیم بنویسیم :
int *ppn=&pn;
بازگشت از نوع ارجاع:
برای فهمیدن این موضوع ابتدا باید در مورد راست مقدارها و چپ مقدارها کمی توضیح بدم
n=5;
در این کد مقدار 5 به n تخصیص داده شده پس با این حساب n می شود چپ مقدار و 5 می شود راست مقدار کلا به هر چیزی که بتواند در طرف چپ معادله قرار بگیرد و مقدارش قابل تغییر باشد را چپ مقدار نامیده و بعقیه را راست مقدار می نامیم مثلا ما نمی توانیم بنویسیم 5=n چون مقدار پنج قابل تغییر نیست و راست مقدار است.
تذکر:متغیرها و بطور کلی اشیاء چپ مقدار هستند و و لیترالها مثل (”abc”, 15) ثابتها و ارایه ها راست مقدارند البته به ارایه ها و ثابتها چپ مقدارهای تغییرناپذیر نیز گفته می شود.
حالا میرسیم به اصل مطلب یعنی اینکه ایا توابع چپ مقدار هستند یا راست مقدار به عبارت ساده تر ایا می شود مقدار برگشتی از یک تابع را به یک عدد تخصیص داد مثل max(m,n) = 50 ؟
در واقع توابع معمولی راست مقدارند ولی اگر ما یک علامت ارجاع یعنی & به اول تابع بصورت زیر اضافه کنیم این تابع چپ مقدار خواهد شد!
int& max(int& m,int& n)
مثال زیر موضوع را روشن می کند:
#include<iostream>
int& max(int& m,int& n)
{
if(m>n)
{
cout<<"max=m \n";
return m;
}
else
{
cout<<"max=n \n";
return n;
}
}
int main()
{
int m=6,n=4;
max(m,n)=3;
max (m,n);
return 0;
}
خروجی برنامه بالا بصورت زیر است:
max=m
max=n
در برنامه بالا ابتدا در تابع max دو مقدار m,n با هم مقایسه می شوند و چون مقدار m بزرگتر از n است عبارت max=m چاپ شده و سپس مقدار m برگردانده می شود در کد اصلی برنامه تابع max که از نوع ارجاع است برابر عبارت 3 قرار می گیرد پس m که اکنون مقدار برگشتی تابع است برابر 3 شده و دوباره تابع max فراخوانده می شود اما اینبار m به 3 تغییر کرده است و در نتیجه عبارت دوم چاپ می شود.
تذکر:توجه داشته باشید که m,n نیز بصورت ارجاع تعریف شده اند زیرا متغیرهای محلی تابع با نابود شدن تابع نابود می شوند و ممکن است برنامه دچار مشکل شود(که 100% این اتفاق خواهد افتاد) به همین دلیل m,n بصورت ارجاع تعریف شده اند به عبارت ساده تر چون وقتی ما متغیری را بصورت ارجاع به تابعی می فرستیم در واقع متغیر جدیدی تولید نشده و تنها ارجاعیست به متغیر برنامه اصلی پس با از بین رفتن تابع متغیر اصلی که درون کد اصلی برنامه است باقی مانده و برنامه دچار مشکل نمی شود .