آموزش زبان برنامه نویسی C قسمت 9

به ایستگاه نهم از دوره ی آموزش زبان سی رسیدیم.در هشت قسمت قبل مطالب زیادی رو یادگرفتید و میتونین برنامه های متنوع و جالبی رو طراحی کنید ! میتونید همه ی قسمت های قبل رو از منوی سایت و در گزینه ی زبان C مطالعه کنید.

این جلسه مبحث مهم و مفهومی رو در پیش خواهیم داشت. پس با دقت ادامه ی مطلب رو دنبال کنید.!

 

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

 

اشاره گرها : 

نوع دیگری از متغیرها در زبان سی وجود داره،به نام اشاره گر (Pointer)! معمولا کسانی که تازه دارن برنامه نویسی یاد میگیرن یا مبتدی هستن،در ابتدا کمی با مفهوم اشاره گر مشکل دارن لذا پیشنهاد میکنم حواستون جمع باشه تا مفهوم پوینترها رو درک کنید چون نقش مهمی در برنامه نویسی سی دارن!

همونطور که گفتم،اشاره گرها هم یک نوع متغیر هستن یعنی مقدارشون میتونه تغییر بکنه (البته اشاره گرهای const هم وجود داره که فعلا راجع به اونها بحث نمیکنیم). اما اشاره گرها چه نوع متغیرهایی هستن ؟! آیا داخلشون یک عدد ذخیره میشه یا مثلا یک رشته ؟!

جواب اینه که داخل اشاره گرها ، آدرس یک خونه ی دیگه از حافظه ی رم قرار داره که خود اون میتونه آدرس متغیری درون برنامه مون باشه!

بذارید یکم راجع به حافظه رم (Random Access Memory) صحبت کنیم! این حافظه به نوعی میزکار کامپیوتر هست یعنی برنامه هایی که شما در کامپیوترتون اجرا میکنید،مقداری از حافظه ی رم رو اشغال میکنن و داده های ورودی و خروجی خودشون رو به صورت موقت در اونجا ذخیره میکنن.این حافظه به خونه (سلول) های خیلی کوچک تقسیم میشه که هرکدوم از این خونه ها یک آدرسی دارن که به صورت هگزادسیمال بیان میشه.(اگه نمیدونید هگزادسیمال چیه،بهتره یک مطالعه ای روی مبناهای عددی داشته باشید).پس هر خونه از رم یک آدرس منحصر به فرد داره و میتونه داخلش یک مقدار ذخیره شده باشه ! 

 

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

 

تعریف اشاره گرها : 

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

 نام اشاره گر*   نوع داده ای که به آن اشاره میشود ;

 

همونطور که میبینید تعریف اشاره گرها مشابه تعریف متغیرهای معمولی ست البته با 2 نکته : 

1 . نوع داده ای که به آن اشاره میشود یعنی متغیری که آدرسش رو ذخیره کردیم از چه نوعیه.

2 . باید از نشانه ی (*) قبل از نام اشاره گر استفاده کنیم.

 

حالا سه تا اشاره گر مختلف رو تعریف میکنیم : 

int *nptr ; 

char *chptr ;

float *avg ;

 

استفاده از ptr در نام اشاره گر میتونه به تشخیص راحت تر اونها و تمییز دادن با متغیرهای معمولی کمک کنه!

 

عملگرهای * و & : 

این دو عملگر برای کار با اشاره گرها استفاده میشن.از عملگر * برای دسترسی به محتوای متغیری که اشاره گر به اون اشاره میکنه و از & برای دسترسی به آدرس یک متغیر استفاده میشه.

شما قبلا با عملگر & در تابع scanf کار کرده بودید و اونجا میگفتید مقداری رو که از کاربر گرفتی در آدرس متغیری که به تابع میدادین ، ذخیره کن.

پس عملگر * ، محتوا و عملگر & ، آدرس ! حالا یکم با این مفاهیم تمرین کنیم : 

 

int a = 4 ;

int *aptr = &a ;

*aptr = 5 ;

printf("%d" , a) ;

// output --> 5

 

خب در مثال بالا یک متغیر و یک اشاره گر (در واقع متغیر اشاره گر! که برای راحتی کار میگیم اشاره گر) تعریف کردیم و آدرس متغیرمون رو داخل اشاره گر قرار دادیم.سپس با عملگر * مقدارش رو برابر با 5 قرار دادیم و اگه مقدار متغیرمون رو چاپ کنیم ، 5 رو خواهیم دید.

 

کمی کار رو پیچیده تر میکنیم : 

float n = 3.14 ;

float **p1 , *p2 ;

p2 = &n ;

p1 = &p2 ;

*(*p1) = 2.71 ;

printf("%.2f" , n) ;

 

خب چیزی که در مثال بالا استفاده کردیم ، اسمش هست : اشاره گر به اشاره گر ! اگه مفهوم قبلی رو متوجه شده باشید با این هم مشکلی ندارید!اشاره گر به اشاره گر ، یک متغیر اشاره گره که به جای اینکه آدرس یک متغیر معمولی درونش ذخیره شده باشه ، آدرس یک اشاره گر رو شامل میشه.که در مثال بالا ما عدد پی رو با کمک اشاره گر به اشاره گری که به متغیر عدد پی اشاره میکرد (واج آرایی !) به عدد اویلر تبدیل کردیم! 

 

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

مثالی که معمولا برای آموزش فراخوانی با ارجاع میزنن و ما هم همون رو بیان میکنیم، تابع Swap هست که مقدار دو متغیر رو با هم عوض میکنه.

در اینجا برای اینکار از یک متغیر موقت (temporary) استفاده میکنیم (روش دیگه ای هم وجود داره که اون رو به خودتون واگذار میکنم که درموردش تحقیق کنید و یادش بگیرید).

 

#include <stdio.h>

#include <conio.h>

 

void swap (int *a , int *b){

    int temp ;

    temp = *(a) ;

    *(a) = *(b) ;

    *(b) = temp ;

}

 

int main(){

    int a = 2 ;

    int b = 5 ;

    printf("Before Swap :\na = %d\nb = %d\n\n" , a,b) ;

    swap(&a , &b) ;

    printf("After Swap :\na = %d\nb = %d" , a,b) ;

    getch() ;

    return 0 ; 

}

 

همونطور که میبینید،پارامترهای تابع رو اشاره گر کردیم و در هنگام ارسال آرگومان ها به جای متغیرها آدرسشون رو ارسال کردیم تا خود متغیر اصلی تغییر کنه.

 

خب دوستان امیدوارم بحث اشاره گرها رو خوب یادگرفته باشید! منتظر قسمت بعدی که آخرین قسمت خواهد بود ، باشین.

بدرود.