اشاره گر در C
اشاره گر چيست؟
يك اشاره گر راهي فراهم مي كند كه بتوان بدون مراجعه مستقيم به يك متغير (يا مدل پيچيده تري از داده ها مثل آرايه)به آن متغير دست يافت. مكانيزمي كه براي اين كار استفاده مي شود ، آدرس متغير است.
دليل استفاده از اشاره گر:
• براي گرفتن بيش از يك خروجي از تابع
• براي ارسال راحتتر و آسان تر رشته ها و آرايه ها از يك تابع به تابع ديگر
• براي ايجاد تغييرات در يك آرايه
• براي دريافت مقادير بازگشتي توابعي همچون Malloc )اين تابع به ميزان درخواستي حافظه در رم رزرو كرده و آدرس شروع اين حافظه را باز مي گرداند(
اشاره گر یک آدرس حافظه است و آدرس حافظه یک عدد است ولی نمی توان آن را در متغییر هایی از نوع int و … ذخیره کرد متغییری که می خواهد اشاره گر را ذخیره کند باید از نوع اشاره گر باشد. برای تعریف متغییر اشاره گر به صورت زیر عمل می کنیم:
;متغییر* نوع
نوع می تواند int ، char و غیره باشد. نکته ای که برای تعریف متغییر اشاره گر باید رعایت شود این است که اگر اشاره گر آدرس متغییری از نوع int را نگه داری می کند باید اشاره گر از نوع int تعریف شود. نوع اشاره گر باید با نوع متغییری که آدرس آن در اشاره گر ذخیره می شود یکسان باشد.به عنوان مثال:
int *i;
این دستور یعنی:
- i متغییر اشاره گری از نوع int است.
- I آدرس محل هایی از حافظه را که محتویات آن ها مقادیری از نوع int هستند را نگه داری می کند.
عمل گر های اشاره گر:
دو عملگر & و * در انجام عملیات با اشاره گر ها مورد استفاده قرار می گیرد.
عملگر & آدرس متغییر را مشخص می کند. و عملگر * محتوای آدرس مورد نظر را مشخص می کند.
به عنوان مثال:
int *p , m , s;
m=5;
p=&m;
s=*p;
- در سطر اول p اشاره گر از نوع int و دو متغییر از نوع int تعریف می شود.
- در سطر دوم مقدار m مساوی 5 می شود.
- در سطر سوم آدرس متغییر m در p قرار داده می شود.
- در سطر چهارم محتویات جایی که آدرس آنجا در p است در s قرار داده می شود. و s=5 می شود.
اعمال روی اشاره گر ها
عمل انتساب اشاره گرها به یکدیگر :
int *p1 , *p2 ;
*p1=*p2;
P1=p2;
- در سطر یک p1 و p2 را اشاره گر از نوع int تعریف کردیم.
- در سطر دوم محتویات آدرس p2 در آدرس p1 جایگزین می شود.
- در سطر سوم آدرس p2 و p1 با یک دیگر برابر شده و هر دو به یک آدرس اشاره می کنند.
فرق دستور دوم و سوم این است که در سطر دوم دو آدرس داریم در هر دو آدرس یک مقدار قرار گرفته و محتوایشان برابر است. ولی در سطر سوم هر دو به یک آدرس یکسان اشاره می کنند.
اعمال جمع و تفریق روی اشاره گر ها:
اعمال جمع و تفریق را می توان بر روی اشاره گرها انجام داد با افزایش یک واحد به اشاره گر به اندازه طول نوعاشاره گر به آن اضافه می شود. به عنوان مثال اگر p یک اشاره گر از نوع int باشد که به محل 1000 حافظه اشاره م کند. P++ موجب می شود تا p به عدد صحیح بعدی اشاره کند. با فرض اینکه طول نوع صحیح 2 بایت باشد. آنگاه p به محل 1002 حافظه اشاره خواهد کرد.
مقایسه اشاره گرها :
اگر p1 و p2 دو اشاره گر باشند می توان آن ها را با هم دیگر مقایسه کرد. به عنوان مثال :
int x , y , *p1 , *p2;
p1 =&x;
p2 = &y;
if (p1=p2){
با این دستور دو اشاره گر p1 و p2 با یک دیگر مقایسه می شوند. فرض کنید p1 به محل 1000 حافظه و p2 به محل 1200 اشاره می کند در این صورت شرط if ارزش نادرستی دارد.
متغییر های پویا (Heap)
اشاره گر می تواند آدرس محلی از حافظه را نگه داری کند و از طریق آدرس آن محل می تواند به محتویات آن محل دسترسی داشته باشد پس نیازی به اینکه محلی که اشاره گر به آن اشاره می کند دارای نام باشد نیست در این روش پس از اینکه یک محل حافظه که اشاره گر به آن اشاره می مند تمام شد می توان آن را آزاد کرد و به سیستم برگرداند.
malloc
ميتوان يک بلوک پيوسته از حافظه را با استفاده از تابع malloc اشغال نمود. مقدار برگشتی تابع آدرس اولين خانه اين بلوک ميباشد. تابع malloc برای گرفتن حافظه از سیستم استفاده می شود که در کتابخانه ی stdlib.h قرار دارد.
(نوع) : نوع اشاره گر را مشخص می کند.
(size) : میزان حافظه به بایت است. و مشخص می کند که چه مقدار از حافظه باید به اشاره گر تخصیص داده شود.
و اگر تابع malloc نتواند حافظه ای از سیستم بگیرد. مقدار تهی (NULL) را در اشاره گر قرار می دهد.
مثال:
int *p;
p= (int*) malloc (sizeof (int));
برگرداندن حافضه به سیستم:
حافضه ی تعریف شده به صورت پویا برای برگردانده شدن به سیستم باید از تابع free() استفاده کرد.این تابع در فایل stdlib.h قرار دارد.
مثال:
free(p);
اشاره گر ها و توابع:
برای ارسال متغییر ها به توابع با روش فراخوانی با ارجاع به جای مقدار متغییر ها ، آدرس آن ها در پارامتر تابع قرار می گیرد. به این ترتیب در تابعی که فراخوانی می شود به آدرس متغییر ها موجود در برنامه دسترسی داریم از طریق آدرس این متغیر ها می توانیم محتویات آن ها را دستکاری کنیم.
مثال:
#include <stdio.h> #include <conio.h> void swap (int* , int*); int main(){ int x=10 , y=20; clscr(); printf("\n first value of x,y are:%d,%d"x,y); swap(&x , &y); printf("\n final value of x,y are:%d,%d"x,y); getch(); return 0; } void swap (int*a , int*b){ int temp; temp=*a; *a = *b; *b = temp; }
چوندر این برنامه تابع باید دو متغییر از تابع اصلی را دستکار یکند هر دو مقدار از طریق فراخوانی با راجاع ارسال می شوند تابع swap برای جابه جایی محتویات دو متغییر از طریق آدرس آنها از متغییر کمکی temp استفاده می کند. ابتدا آنچه که در x است در temp قرار می گیرد. سپس آنچه که در y است در x قرار می گیرد ودر آخر محتویات temp در y قرار می گیرد. خروجی این برنامه به صورت زیر است.
first value of x,y are: 10,20
final value of x,y are: 20,10
سلام.
من آدرس لینک این پستتون رو توی سایتم پست کردم.اگه مشلی هست بگین پاکش می کنم 🙂
نه مشکلی نیست