متغیرها  در زبان C

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

نحوه تعریف متغیرها

متغیر ها به صورت زیر تعریف می شوند :

;مقدار اولیه = نام متغیر نوع متغیر

مثال

Unsigned char A=12;

int a,X,j;

توضیح :  در خط اول یک متغیر 8 بیتی بدون علامت با نام A  که تنها میتواند مقادیر 0  تا 255  بگیرد ، با  مقدار اولیه 12 تعریف شده است . در خط دوم نیز3 متغیر علامت دار با نام های a و X و j  که هر سه مقدار  اولیه 0 دارند تعریف شده است.

نکته :
در صورت عدم تعریف مقدار اولیه در هنگام تعریف یک متغیر ، مقدار اولیه در حالت default  برابر 0 تعریف می شود.

ویژگی های نام متغیر

  • اولین کاراکتر نام متغیر عدد نمیتواند باشد .
  • نام متغیر بیشتر از 31 کاراکتر مورد استفاده نیست .
  • نام متغیر تنها ترکیبی از حروف a تا z و A تا Z  و اعداد و کاراکتر _ می تواند باشد .

انواع متغیر ها از نظر محل تعریف در برنامه

متغیرها از نظر مکانی که در برنامه تعریف می شوند ، به دو دسته کلی تقسیم می شوند :

  • متغیرهای عمومی ( Global )
  • متغیرهای محلی ( Local )

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

محل تعریف متغیرها در حافظه میکروکنترلر

زمانی که یک متغیر به صورتی که در بالا گفته شد ، تعریف می شود آن متغیر در اولین مکان خالی در حافظه SRAM   ذخیره می شود. برای تعریف متغیر در حافظه EEPROM  از کلمه کلیدی eeprom  و برای تعریف متغیر در حافظه FLASH از کلمه کلیدی flash  قبل از تعریف متغیر استفاده می شود. بنابراین باید توجه داشت که با قطع منبع تغذیه کلیه حافظه SRAM  پاک خواهد شد و متغیرهایی که باید ذخیره دائمی شوند می بایست در حافظه EEPROM یا FLASH تعریف و ذخیره شوند.

 مثال :

int a;

eeprom char b;

flash float c;

نکته :
همانطور که قبلا گفتیم ، حافظه Flash ، حافظه برنامه کاربر است یعنی برنامه به زبان C  بعد  از کامپایل و ساخته شدن توسط کدویژن و پروگرام شدن روی میکروکنترلر در حافظه Flash  ذخیره می شود. بنابراین برای تعریف متغیر در حافظه Flash تنها در صورت خالی بودن قسمتی از آن امکان پذیر است .
نکته :
حافظه SRAM  تنها با قطع تغذیه پاک می شود و میتوان کاری کرد که  با ریست شدن میکرو متغیرهای عمومی موجود در SRAM ریست نشده و مقدار قبلی خود را حفظ نمایند.

توابع در زبان c

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

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

تابع اصلی برنامه نویسی به زبان C تابع main  نام دارد که در تمامی برنامه ها وجود داشته و بدون ورودی و خروجی است . توابع دیگر را می توان در بالای تابع main ، در پایین تابع main  و یا در فایل های کتابخانه ای تعریف کرد.

انواع توابع در زبان c

هر تابع مجموعه ای از دستورات است که بر روی داده ها پردازش انجام می دهد.  ورودی و خروجی یک تابع  مقادیری هستند که تابع در برنامه دریافت می کند و به برنامه باز می گرداند. توابع بر اساس ورودی و خروجی  به 4 دسته زیر تقسیم می شود :

  • تابع با ورودی ، با خروجی

مثال : تابع با دو ورودی از جنس کاراکتر و یک خروجی از جنس کاراکتر

Char F1( char x , char y );

  • تابع با ورودی ، بدون خروجی

مثال : تابع دارای یک ورودی int و بدون خروجی

void F2( int x );

  • تابع بدون ورودی ، با خروجی

مثال : تابع بدون ورودی اما دارای خروجی int

int F3(void);

  • تابع بدون ورودی ، بدون خروجی

مثال : تابع بدون ورودی و خروجی

void F4(void);

بنابراین در اولین قدم باید مشخص کنیم که این تابع چه خروجی را به ما می دهد (در اصطلاح برنامه‌نویسی برمی‌گرداند) و فقط به ذکر نوع خروجی بسنده می کنیم ، یعنی مثلا اگر عدد صحیح برگرداند از int  ، اگر کاراکتر برگرداند از char و به همین ترتیب برای انواع دیگر و اگر هیچ مقداری را برنگرداند از void  استفاده می کنیم .

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

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

بنابراین در زبان c  توابع حداکثر دارای یک خروجی می باشند و اگر تابعی خروجی داشته باشد آن را باید با دستور return به خروجی تابع و برنامه اصلی بر گردانیم .

تعریف توابع در زبان c

برای نوشتن و اضافه کردن یک تابع باید دقت کرد که هر تابع سه بخش دارد : اعلان تابع ، بدنه تابع و فراخوانی تابع

نحوه تعریف تابع به یکی از سه صورت زیر است :

  • اعلان تابع قبل از تابع main باشد و بدنه تابع بعد از تابع main باشد .
  • اعلان تابع و بدنه تابع هر دو قبل از تابع main باشد .
  • اعلان تابع و بدنه تابع درون فایل کتابخانه ای باشد .

فراخوانی تابع نیز در درون تابع main  صورت می گیرد . در صورتی که اعلان و فراخوانی تابع درون فایل  کتابخانه ای باشد فقط نیاز به فراخوانی آن در main است .

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

اعلان و بدنه تابع

یک تابع به صورت زیر اعلان می شود. اعلان تابع همیشه قبل از تابع main باید صورت گیرد.

;(… , نام ورودی دوم  نوع ورودی دوم , نام ورودی اول  نوع ورودی اول ) نام تابع  نوع داده خروجی تابع

مثال :

void sample ( int x, int y );

بدنه تابع می تواند قبل از تابع main  و یا بعد از آن باشد.  در صورتی که بخواهیم بدنه  تابع بعد از main  باشد آن را به صورت فوق اعلان می کنیم و بعد از تابع main  به صورت زیر دوباره اعلان را به همراه بدنه تابع می نویسیم.

(…, نام ورودی دوم  نوع ورودی دوم , نام ورودی اول  نوع ورودی اول ) نام تابع  نوع داده خروجی تابع

}

بدنه تابع : دستوراتی که تابع انجام می دهد

{

مثال:

void sample ( int x, int y );

void main ( void )

{

…

}

void sample ( int x, int y )

{

.

.

.

}

در صورتی که بخواهیم بدنه تابع قبل از تابع main  باشد ، به همان صورت فوق این کار را انجام می دهیم با این تفاوت که یکجا هم اعلان و هم بدنه قبل از main تعریف می شود   و دیگر بعد از تابع main  چیزی نمی آید.

مثال :

void sample ( int x, int y )
{
.
.
.
}
void main ( void )
{
…
}

فراخوانی تابع

صدا زدن تابع درون برنامه را فراخوانی گویند . در فراخوانی توابع باید نام تابع و مقدار ورودی ها را بیان کنیم که به آن آرگومانهای تابع نیز گفته می شود . در مقدار دهی آرگومان تابع در هنگام فراخوانی دیگر نباید نوع آرگومانها را ذکر کنیم.

مثال :

void main(void)
{
...
sample (a, b);
...
}

 

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

مثال :

#include <mega32.h>
#include <delay.h>
unsigned char i=0;
unsigned char count (void) {
i++;
delay_ms(300);
return i;
}
void main (void) {
DDRA=0xff;
PORTA=0x00;
while(1){
PORTA= count();
}
}

توضیح : در برنامه فوق ابتدا هدرفایل مربوط به میکروکنترلر Atmega32  به برنامه اضافه می شود . با اضافه شدن این فایل برنامه تمام رجیسترهای میکروکنترلر را می شناسد . سپس هدر فایل delay  برای اینکه بتوان از تابع delay_ms  استفاده کرد به برنامه اضافه شده است . سپس یک متغیر 8 بیتی از نوع عدد بدون علامت ( unsigned char ) با مقدار اولیه صفر تعریف می شود. یک تابع دارای خروجی و بدون ورود ی اعلان و بدنه آن تعریف شده است. در تابع main ابتدا رجیستر DDRA  به منظور اینکه تمام 8 بیت موجود در پورت A  خروجی شود ، به صورت 0xff  مقدار دهی شده است. مقدار اولیه منطق پایه های خروجی پورت A  در خط  بعدی همگی برابر 0 شده است . در نهایت در حلقه بی نهایت while  ، تابع فراخوانی شده است و مقدار خروجی که تابع برمیگرداند در درون PORTA ریخته می شود . در صورتی که روی هر پایه از پورت LED قرار دهیم ، برنامه به صورت شمارنده عمل خواهد کرد و در هر مرحله تعدادی LED روشن می گردد .

نکته :
نوع متغیر رجیسترها در هدرفایل mega32.h  همگی به علت 8 بیتی بودن رجیسترها در میکروکنترلرهای AVR ، از نوع unsigned char می باشد.