کلاسهای حافظه
تاکنون برنامه هایی را نوشته ایم که در بعضی از آنها از چند تابع نیز استفاده
شده است . در این برنامه ها متغیرهای مورد نیاز هر تابع را در همان تابع تعریف
کرده ایم . متغیرهایی که در یک تابع تعریف می شوند در موقع انتقال کنترل اجرای
برنامه به آن تابع ایجاد شده ( حافظه به آنها تخصیص داده می شود ) و در موقع
برگشت کنترل اجرای برنامه از آن تابع ، حافظه تخصیص یافته به متغیرهای آن تابع
از آنها اخذ میشود و به سیستم عامل برگردانده خواهد شد. یعنی این گونه متغیرها
فقط در همان تابعی که تعریف یم شوند اعتبار دارند و در تابع دیگر قابل استفاده
نیستند . این مساله حتی در مورد متغیرهای همنام نیز صادق است . بدین معنی که
اگر به عنوان مثال متغیری به نام I در تابع اصلی (()main) وجود داشته باشد و
متغیری تحت همین نام در تابع فرعی دیگری که توسط تابع ()main فراخوانی می شود
تعریف گردد این دو متغیر کاملا” از یکدیگر مجزا خواهند بود و در حافظه ، دو محل
جداگانه برای آنها در نظر گرفته می شود و هرگونه تغییر در یکی از آنها ، در
دیگری تاثیری نخواهد داشت .
مثال ۱: برنامه ای که چگونگی استفاده از متغیرهای همنام را در توابع مختلف
نشان می دهد . main)(
{
int i ;
printf(“enter the value of i:” );
scanf(“%d”/&i );
input )(;
printf(“\nvalue of i in main is:”);
print(“%d”/i );
}
input)(
{
int i ;
printf(“enter value of i”);
printf(“(in function:)”);
scanf(“%d”/&i );
printf(“\nvalue of i in function is:”);
printf(“%d”/i);
}
به نمونه ای از خروجی حاصل از اجرای برنامه مثال ۱ که درپاسخ به اولین دستور scanf
عدد ۱۰ و در پاسخ به دومین دستورscanf عدد ۴۰ وارد شده است توجه نمایید: enter the value of i:10
enter vale of i(in function:)40
vale of i in function is: 40
value of i in main is : 10
با مطالبی که تاکنون گفته شد روشن گردید که متغیرهایی که در یک تابع تعریف
میشوند فقط درهمان تابع قابل استفاده هستند و به محض برگشت کنترل اجرای برنامه
از آن تابع ، این متغیرها عملا” وجود ندارند. به چنین متغیرهایی که محدوده حضور
آنها فقط در تابعی است که در آن تابع تعریف شده اند متغیرهای محلی گفته می شود.
همه متغیرها در زبان C دارای چنین خصیصه ای نیستند. بلکه انواع دیگری ازمتغیرها
نیز وجود دارند که برای معرفی آنها لازم است به تشریح کلاس حافظه بپردازیم .
کلاس حافظه هر متغیر دو چیز را برای آن متغیر مشخص می کند : ۱
مدت حضور آن در برنامه یا طول عمر (life time) متغیر . ۲
محدوده حضور آن در برنامه (scope vvisibility) .
یکی از علل مطالعه کلاس های حافظه این است که با داشتن اطلاعاتی در مورد مدت
حضور متغیرها در برنامه و همچنین محدوده حضور آنها ، می توانیم برنامه هایی
بنویسیم که : ۱
از حافظه کامپیوتر به نحو خوبی استفاده گردد . ۲
سرعت اجرای آنها بالا باشد . ۳
برنامه ها کمتر با خطا مواجه شوند و عیب یابی سهل تر گردد .
کلاس های حافظه ای که در زبان C از آنها استفاده می شود عبارتند از :
۱
کلاس حافظه اتوماتیک (automatic) . 2
کلاس حافظه استاتیک (static) . 3
کلاس حافظه ثبات (register) . 4
کلاس حافظه خارجی (extern) .
کلمات کلیدی auto، static،، register،و externو بترتیب مشخص کننده کلاس های
حافظه اتوماتیک ، استاتیک ، ثبات و خارجی هستند. این کلمات قبل از کلمات کلیدی
تعیین نوع متغیر بکار می روند .
شکل کلی تعیین کلاس های حافظه بصورت زیر است : ;
<کلاس حافظه > <نوع متغیر> <اسامی متغیرها>
بعنوان مثال دستور auto int i/y ; متغیرهای iو yو را از نوع ” صحیح ” و با
کلاس حافظه اتوماتیک تعریف می نماید .
کلاس حافظه اتوماتیک
متغیرهایی با کلاس حافظه اتوماتیک ، بیشتر ازسایر انواع متغیرها مورداستفاده
قرار می گیرند . متغیرهایی که تاکنون در برنامه ها استفاده شده اند ، دارای کلاس
حافظه اتوماتیک بوده اند. یعنی در زبان C متغیرها در حالت عادی دارای کلاس حافظه
اتوماتیک هستند . متغیرهای با کلاس حافظه اتوماتیک دارای خصوصیات زیر می باشند: ۱
وقتی در یک تابع و یا یک بلاک تعریف می شوند فقط درآن تابع و یا بلاک قابل
دسترسی اند ( ” محلی ” آن تابع و یا بلاک محسوب می شوند ) . ۲
در موقع ورود به تابع و یا بلاک به آنها حافظه اختصاص می یابد . ۳
در هنگام خروج از تابع و یا بلاک ، حافظه اختصاص یافته به آنها، پس گرفته
می شود .
مثال ۲: برنامه ای که تعریف متغیرهای اتوماتیک در بلاک را نشان می دهد . main)(
{
int sum=10 ;
{
float sum=3.1416;
printf(“\n sum in block is:”);
printf(%6.4f\n”/sum );
}
printf(“\n sum out of block is:”);
printf(“%2d\n/sum );
}
نمونه ای از خروجی حاصل از اجرای برنامه مثال ۲ در ذیل آمده است : sum in block is:3.1416
sum out of block is:10
متغیرهای اتوماتیک می توانند مقدار اولیه بگیرند . اگر ارزش اولیه این گونه
متغیرها در تابعی صورت گیرد که این تابع چندین بار فراخوانی می گردد ، هر بار
اجرای تابع ، مقدار اولیه به آن میگردد ( برخلاف متغیرهای با کلاس حافظه استاتیک
که ارزش دهی اولیه فقط یکبار انجام می شود ) .
مثال ۳: استفاده از متغیرهای با کلاس حافظه اتوماتیک که دارای ارزش اولیه
می باشند . main)(
{
auto int k ;
void aquare )(;
for(k=1;k<5;k++)
aquare(k);
}
void square(d)
int d;
{
int squared=d^d ;
printf(“\n%2d squared is” );
printf(” %3d\n”/d/squared);
}
خروجی حاصل از اجرای برنامه مثال ۳ : ۱ squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
متغیرهای عمومی و کلاس حافظه خارجی
همانطور که قبلا” گفته شد متغیرهای تعریف شده در یک تابع و یا یک بلاک فقط در
همان تابع و یا بلاک اعتبار دارند . اینگونه متغیرها را متغیرهای محلی نامگذاری
کردیم . نوع دیگری از متغیرها در زبان C قابل استفاده هستند که در کلیه توابع
موجود در برنامه قابل دسترسی اند. به این متغیرها، متغیرهای عمومی گفته میشود.
متغیرهای عمومی در خارج از تابع اصلی تعریف می شوند .
مثال ۴: برنامه ای که نحوه استفاده از متغیرهای عمومی را نشان می دهد . این
برنامه تعداد ۵ عدد رااز ورودی خوانده و مجموع مربعات آنهارا محاسبه می نماید. int k/sq ;
int sum=0 ;
main)(
{
auto j/i=5 ;
printf(“\n enter five number:” );
for(j=0 ;j
input )(;
printf(“\n sum of square is:%d”/sum);
}
input)(
{
scanf(“%d”/&k );
square )(;
sum+=sq ;
}
square)(
{
sq=k*k ;
}
نمونه ای از خروجی حاصل از اجرای برنامه مثال ۴ : enter five number: 10 12 4 7 20
sum of square is:709
در مثال ۴ متغیرهای sq، k،و sumو در خارج از تابع ()main تعریف شده اند و در
توابع ()square و ()input بدون تعریف این متغیرها از آنها استفاده شده است .
اگر توابع تعریف شده در یک برنامه علاوه بر متغیرهای عمومی از متغیرهای محلی
نیز استفاده نمایند و یک یا چند متغیر محلی توابع ، با یک یا چند متغیر عمومی
مراجعه داشته باشد ( مقدار آنرا تغییر دهد و یا مقدار آن متغیر را مورداستفاده
قرار دهد ) تاثیری در متغیر عمومی همنام با این متغیر محلی نخواهد داشت .
مثال ۵: برنامه ای که توابع موجود در آن علاوه بر استفاده از متغیرهای عمومی
از متغیرهای محلی همنام با متغیرهای عمومی نیز استفاده می کنند . int count ;
main)(
{
count=100 ;
func1 )(;
}
func1)(
{
int temp ;
temp=count ;
func2 )(;
printf(“\n count is:%d”/count );
}
func2)(
{
int count ;
for(count=1/count<6;count++)
printf(” %c “/’*’
}
خروجی حاصل از اجرای برنامه مثال ۵ : * * * * *
count is :100
در مثال ۵ متغیر count که قبل از تابع ()main تعریف شد، یک متغیر عمومی است
و متغیر count که در تابع ()func1 بکار رفته است ، همین متغیر میباشد. در تابع
()func2 متغیری به نام count تعریف شد که محلی این تابع می باشد . لذا در این
تابع هر مراجعه به متغیر count مراجعه به متغیری است که در این تابع تعریف شده
است .
درشروع اجرای برنامه برای متغیرهای عمومی ، حافظه اختصاص می یابد و درپایان
اجرای برنامه ، این حافظه از متغیرها اخذ می گردد. بنابراین اگر تعداد متغیرهای
عمومی زیاد باشد تاثیر بسزایی در میزان حافظه مصرفی دارد . بهر حال در مواقعی
که توابع موجود در برنامه به متغیرهای مشترکی نیاز داشته باشند ، خوب است از
متغیرهای عمومی استفاده گردد. ولی باید توجه داشت متغیرهایی که بندرت در سراسر
برنامه مورد استفاده قرار می گیرند ، بصورت متغیرهای عمومی تعریف نگردند .
اگر برنامه هایی که به زبان C نوشته می شود طولانی باشد ، می توان آن برنامه
را به قسمت های منطقی کوچکتری تقسیم کرده ، سپس هر قسمت را در یک فایل قرار
داده و پس از کامپایل کردن آنها به طور مجزا ، همه قسمت ها را با یکدیگر اجرا
نمود . به هر یک از این قسمت های مجزا ، یک واحد (unit) گفته می شود . اگر
متغیرهایی در واحد اصلی تعریف شوند و بخواهیم از آنها در واحدهای فرعی دیگر
استفاده کنیم ( بدون این که در واحدهای فرعی به آنها حافظه ای اختصاص یابد )
باید در واحدهای فرعی توسط کلمه کلیدی extern به کامپایلر گفته شود که این
متغیرها در جای دیگری ( در واحد اصلی ) تعریف شده اند. در غیر این صورت استفاده
از متغیرهای مورد نظر در واحدهای دیگر ممکن نیست ( جدول ۱ ) .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | file1 file2 |
| int s/y; extern int x/ y; |
| char ch; extern char ch; |
| main )(func 22 )(|
| { { |
| x=y/10; |
| } } |
| func 1 )(func 23 )(|
| { { |
| x=123; y=10; |
| } } |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
جدول (۱) . کاربرد extern در واحدهای مختلف یک برنامه
در جدول ۱ کلمه کلیدی extern به کامپایلر می گوید که متغیرهای x، y،و chو
قبلا” در جای دیگری تعریف شده اند ، لذا در برنامه file2 حافظه جدیدی به آنها
اختصاص نمی یابد .
استفاده از کلمه کلیدی extern درتوابع موجود در یک فایل نیز امکان پذیر است
که البته نیازی به آن نیست ( کاربرد extern در این گونه موارد اختیاری است ) .
مثال ۶: برنامه ای که کاربرد کلمه کلیدی extern را در یک فایل نشان می دهد . int first/second ;
main)(
{
extern int first/second ;
printf(“\n enter two number: ” );
scanf(“%d%d”/&first/&second );
printf(“\nsum is :%d”/first+second);
}
به نمونه ای از خروجی برنامه مثال ۶ توجه نمایید : enter two number: 15 30
sum is:45
در برنامه مثال ۶ دو متغیر firstو secondو در خارج از تابع ()main تعریف
شده اند . دستور extern در تابع ()main به کامپایلر می گوید که این متغیرها در
جای دیگری ( در خارج از تابع اصلی ) تعریف شده اند . البته همانطور که گفته شد
توابعی که در یک فایل وجود دارند می توانند از متغیرهای عمومی استفاده کنند و
نیاز به معرفی آنها توسط extern نیست .
متغیرهای عمومی ، دارای کلاس حافظه خارجی (extern) هستند و دارای دو خصیصه
زیر می باشند : ۱
طول عمر این متغیرها ، از بدو اجرای برنامه تا خاتمه اجرای آن است . ۲
محدوده حضور آنها در سراسر یک برنامه است .
کلاس حافظه استاتیک
متغیرهایی که دارای کلاس حافظه استاتیک هستند می توانند به دو دسته تقسیم
شوند :
الف ) متغیرهای استاتیک محلی
ب ) متغیرهای استاتیک عمومی
متغیرهای استاتیک محلی دارای خواص زیر هستند : ۱
فقط در همان تابعی که تعریف شده اند قابل دسترسی اند ( حضور دارند ) . ۲
در هنگام خروج از تابع ، مقادیر متغیرها آخرین مقداری خواهد بود که در
تابع به آنها اختصاص یافته است . ۳
می توانند مقدار اولیه بگیرند . ۴
اگر متغیر استاتیک محلی مقدار اولیه بگیرد ، این ارزش دهی اولیه ، فقط
یکبار صورت می گیرد ( این مطلب را از مورد ۲ نیز می توان نتیجه گرفت ) .
مثال ۷: main)(
{
int i ;
void subroutine )(;
for(i=0 ; i<5 ; i++)
subroutine )(;
}
void subroutine)(
{
static int static_var=0 ;
int auto_var=0 ;
printf(“\nautomatic=%d/”/auto_var);
printf(“static=%d”‘static_var );
auto_var ++;
static_var ++ ;
}
خروجی حاصل از اجرای برنامه مثال ۷ : automatic=0/static=0
automatic=0/static=1
automatic=0/static=2
automatic=0/static=3
automatic=0/static=4
متغیرهای استاتیک عمومی فقط در یک فایل ( در یک واحد ) از برنامه ، از جایی
که تعریف می شوند به بعد قابل دسترسی اند ( برخلاف متغیرهای عمومی غیر استاتیک
که در همه واحدهای یک برنامه قابل دسترسی اند ) . مثال های ۸و ۹و .
مثال ۸: static int i/j ;
main)(
{
.
.
.
}
f1)(
{
.
.
.
}
f2)(
{
.
.
.
}
در مثال ۸ متغیرهای xو yو در تابع ()main و کلیه توابعی که بعد از آن تعریف
می شوند قابل استفاده اند .
مثال ۹: main)(
{
.
.
.
}
f1)(
{
.
.
.
}
static x/y ;
f2)(
{
.
.
.
}
f3)(
{
.
.
.
}
در مثال ۹ ، متغیرهای xو yو در توابع ()main و ()f1 قابل دسترسی نیستند ولی
در دو تابع ()f2 و ()f3 و کلیه توابعی که بعداز آن تعریف میشوند، قابل استفاده
هستند .
استفاده کلاس حافظه استاتیک درپنهان سازی اطلاعات (information hide) میباشد.
کلاس حافظه ثبات
ذخیره هایی که دارای کلاس حافظه هستند در صورت امکان در یکی از ثبات های CPU
قرار می گیرند . لذا سرعت انجام عملیات با آنها بسیار بالا است و موجب افزایش
سرعت اجرای برنامه می شود . کلیه متغیرهای اتوماتیک و آرگومان های توابع
می توانند دارای کلاس حافظه ثبات باشند .
در مورد کلاس حافظه ثبات محدودیتهای زیر را داریم : ۱
از آنجایی که تعداد ثباتهای CPU محدود است ، تعداد کمی از متغیرها را
می توان با کلاس حافظه ثبات تعریف کرد . اگر تعداد متغیرهای با کلاس حافظه ثبات
زیاد باشد کامپایلر کلاس حافظه ثبات را از متغیرها حذف می کند . ۲
انواع متغیرهایی که میتوانند دارای کلاس حافظه ثبات باشند، درکامپیوترهای
مختلف متفاوت است و معمولا” نوع های int، char،و pointerو می توانند دارای کلاس
حافظه ثبات باشند . ۳
آدرس متغیری که دارای کلاس حافظه ثبات باشد، عملا” مفهوم نخواهد داشت و یا
به عبارت دیگر، عملگر & را نمیتوان برای متغیرهای با کلاس حافظه ثبات بکار گرفت
( چون این متغیرها در ثبات CPU قرار دارند ) .
مثال ۱۰: int n/fact=1 ;
main)(
{
printf(“\n enter a number(1-9: )”);
scanf(“%d/&n );
factolial )(;
printf(“\nfactolial of number:%d”/n);
printf(” is :%d”/fact );
}
factorial)(
{
register int i ;
for(i=2 ; i<=n ; i++)
fact *=i ;
}
دیدگاه خود را بیان کنید.
باید وارد سایت شده باشید برای دیدگاه دادن