خوش آموز درخت تو گر بار دانش بگیرد، به زیر آوری چرخ نیلوفری را


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

آموزش زبان ++C : متغیرها : معرفی، مقدار دهی اولیه و انتساب
نویسنده : امیر انصاری
آدرسهای حافظه

سیستم یکپارچۀ سازمانی راهکار



در آموزشهای مبانی ++C در مورد متغیرها صحبت هایی را کردیم و آموزشهایی را ارائه دادیم، در این درس و چند درس بعدی، آن آموزشها را تکمیل خواهیم کرد.

در آموزشهای قبلی گفتیم که متغیرها در واقع یک نام برای بخشی از حافظه می باشند و می توان مقادیری را در آن بخش از حافظه ذخیره کرد. به طور خلاصه، کامپیوترها دارای یک حافظه با دسترسی تصادفی با نام RAM (random access memory) می باشند که این حافظه در اختیار برنامه ها قرار دارد و می توانند از آن استفاده کنند. هنگامی که یک متغیر معرفی می شود، بخشی از حافظه RAM به آن متغیر تخصیص می یابد.

کوچکترین بخش حافظه یک رقم باینری (bit) می باشد که می تواند مقادیر 0 یا 1 را در خودش ذخیره کند. شما می توانید به آن همانند یک لامپ نگاه کنید، اگر لامپ روشن باشد مقدار 1 و اگر لامپ خاموش باشد مقدار 0 را دارد. هیچ وضعیت دیگری ما بین این دو وضعیت 0 و 1 وجود ندارد. در واقع اگر بخواهیم به آنچه روی حافظه قرار دارد نگاهی بیندازیم همه چیز به شکل 011010100101010 و یا ترکیبهای دیگری از 0 و 1 می باشند. حافظه کامپیوتر در واحدهای متوالی که آدرس های حافظه (memory addresses) نامیده می شوند تقسیم بندی شده است. مشابه آدرس یک خیابان که برای پیدا کردن آن خیابان می تواند به کار آید، آدرس های حافظه نیز به ما این امکان را می دهند تا محتویات بخش خاصی از حافظه را پیدا کنیم و به آن دسترسی داشته باشیم. شاید شگفت آور باشد که در کامپیوترهای مدرن، هر بیت آدرس خاص خودش را ندارد. در واقع کوچکترین واحد حافظه که دارای آدرس می باشد به عنوان بایت (byte) شناخته می شود. استاندارد مدرن اینست که هر بایت متشکل از 8 بیت متوالی می باشد. توجه داشته باشید که در برخی از ماشین های خیلی قدیمی اندازه بایت ها متفاوت می باشد، اگر چه به صورت عمومی ما در مورد آنها نگرانی نخواهیم داشت. در این دوره آموزشی ما فرض می کنیم که بایت برابر با 8 بیت می باشد.

تصویر زیر، چند آدرس ترتیبی حافظه را همراه با مقادیر داخل آنها نشان می دهد :

آموزش زبان ++C : متغیرها : معرفی، مقدار دهی اولیه و انتساب
از آنجا که تمامی اطلاعات موجود در کامپیوتر فقط یک توالی از بیت ها می باشند، ما از انواع داده (data type) استفاده می کنیم تا به ما بگوید چگونه با محتویات آن بخش از حافظه به روش معنا داری برخورد کنیم. شما تا الان از نوع داده integer استفاده کرده اید. در واقع وقتی یک متغیر از نوع integer را معرفی می کنیم اطلاعات موجود در آن بخش از حافظه به عدد صحیح تفسیر می گردد.

هنگامی که یک مقدار را به یک نوع داده منتسب می کنید، کامپایلر و CPU مراقب جزئیات رمزگذاری (encoding) داده های شما هستند تا بیت ها را برای آن نوع داده مراقبت کنند. هنگامی هم که می خواهید محتویات آن بخش از حافظه را بخوانید، عدد مربوطه از روی آن اطلاعات تبدیل به بیت شده، باز سازی می گردد.

علاوه بر نوع داده integer انواع داده های دیگری نیز در زبان برنامه نویسی ++C وجود دارند.

انواع داده های اصلی


زبان برنامه نویسی ++C همراه با چند نوع داده (data type) داخلی ارائه شده است. اینها را انواع داده های اصلی ++C می نامند. همچنین به انواع داده اصلی ++C به صورت غیر رسمی basic types، primitive types و همینطور built-in types نیز گفته می شود.

در ادامه لیستی از انواع داده های اصلی در زبان برنامه نویسی ++C آمده است :

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

معرفی یک متغیر


در قسمت مبانی ++C شما با چگونگی معرفی متغیرهای از نوع integer آشنا شدید :

int nVarName; // int is the type, nVarName is the name of the variable

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

type varName; // type is the type (eg. int), varName is the name of the variable

در مثال زیر، ما 5 متغیر از 5 نوع داده مختلف را معرفی کرده ایم :

bool bValue;
char chValue;
int nValue;
float fValue;
double dValue;

توجه داشته باشید که نوع void متفاوت از سایر انواع می باشد و قوانین خاصی برای استفاده از آن وجود دارد. بنابراین کد زیر کار نخواهد کرد و صحیح نمی باشد :

void vValue; // won't work, void can't be used as a type for variable definitions

مقدار دهی اولیه متغیرها (Variable initialization)


هنگامی که یک متغیر را معرفی می کنید، می توانید فوراً به آن متغیر مقداری را بدهید. این کار را مقدار دهی اولیه متغیرها (Variable initialization) می نامند. که به اختصار به آن مقدار دهی اولیه (initialization) نیز گفته می شود.

در زبان برنامه نویسی ++C برای مقدار دهی اولیه (initialization) متغیرها سه روش وجود دارد. اول اینکه می توانیم با استفاده از یک علامت برابری (=) این کار را انجام بدهیم، اسم این روش copy initialization می باشد :

int nValue = 5; // copy initialization

توجه داشته باشید که علامت برابری (=) در اینجا تنها بخشی از گرامر (syntax) زبان می باشد و با آن علامت برابری (=) که بعد از معرفی شدن متغیر استفاده می کنید، یکسان نمی باشد.

روش دوم استفاده از پرانتزها برای مقدار دهی اولیه متغیرها می باشد که به آن direct initialization گفته می شود :

int nValue(5); // direct initialization

اگر چه روش direct initialization در ظاهر شبیه فراخوانی توابع می باشد، اما کامپایلر بین این دو فرق می گذارد و می تواند تشخیص بدهد که کدام یک مقدار دهی اولیه متغیر و کدام یک فراخوانی تابع می باشد.

روش direct initialization در برخی جاها می تواند بهتر از روش copy initialization عمل کند، و یکسری مزایای دیگر نیز دارد که در مبحث کلاسها (classes) بیشتر در مورد آن صحبت خواهیم کرد. همچنین روش direct initialization به ما کمک می کند تا بین مقدار دهی اولیه (initialization) و انتساب (assignment) تمایز قائل شویم. در نتیجه، توصیه ما اینست که در هنگام مقدار دهی اولیه متغیرها روش direct initialization را به کار ببرید.

قانون : ترجیح شما این باشد که برای مقدار دهی اولیه متغیرها از روش direct initialization استفاده کنید.

روش Uniform initialization در ++C نسخه 11


از آنجا که زبان ++C به صورت ارگانیک مدام در حال رشد می باشد، روش های copy initialization و direct initialization تنها در مورد برخی از انواع متغیرها کار می کنند (برای مثال شما نمی توانید از این دو روش برای مقدار دهی اولیه لیستی از متغیرها استفاده کنید).

در C++ 11 یک مکانیزم دیگر با نام Uniform initialization اضافه شده است که به آن brace initialization نیز گفته می شود :

int value{5};

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

int value{}; // default initialization to 0

روش Uniform initialization یک سری مزایای افزوده دارد که narrowing در تبدیل داده ها یکی از این مزایا می باشد. narrowing به این معنا می باشد که اگر بخواهید با استفاده از روش Uniform initialization به یک متغیر مقدار اولیه بدهید، و آن متغیر نتواند آن مقدار اولیه را به صورت امن نگهداری کند، کامپایلر تولید یک خطا یا یک هشدار خواهد کرد. برای مثال :

int value{4.5}; // error: an integer variable can not hold a non-integer value

قانون : اگر از C++ 11 یا بالاتر استفاده می کنید روش Uniform initialization بر سایر روشهای مقدار دهی اولیه ارجحیت دارد.

انتساب دادن مقادیر به متغیرها (Variable assignment)


هنگامی که به یک متغیر بعد از معرفی شدن آن مقداری را بدهید، به این روش copy assignment یا به اختصار assignment (انتساب یا تخصیص دادن) گفته می شود.

int nValue;
nValue = 5; // copy assignment

زبان ++C هیچ روش داخلی برای direct assignment و یا uniform assignment ندارد.

متغیرهای بدون مقدار اولیه (Uninitialized variables)


متغیری که مقدار دهی اولیه نشده باشد Uninitialized variable نامیده می شود. در زبان برنامه نویسی ++C یک متغیر بدون مقدار اولیه، به صورت پیش فرض یک مقدار زباله (garbage) دارد که در واقع این مقدار، همان مقدار موجود در آن مکان حافظه می باشد. این مقدار زباله تا زمانی که مقداری به متغیر نسبت داده شود، در آن خواهد بود.

یادداشت جانبی : زبان ++C یک سری انواع غیر اصلی (non-fundamental) نیز دارد، مانند pointers، structs و classes . برخی از این انواع به صورت پیش فرض مقدار دهی اولیه نمی شوند، و برخی دیگر مقدار دهی اولیه می شوند. در آموزش های آینده در مورد این انواع صحبت خواهیم کرد. برای الان، بهتر است فرض کنید که هیچ کدام از انواع ++C مقدار دهی پیش فرض اولیه ندارند.

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

تعریف چندین متغیر (Defining multiple variables)


شما می توانید متغیرهایی از یک نوع را در یک بیانیه (statement) به صورت یکجا تعریف کنید. در این روش اسامی متغیرها را با کاما (comma) از یکدیگر جدا کنید. دو قطعه کد زیر از نظر نتیجه کار، کاملاً یکسان هستند :

int a, b;

int a;
int b;

شما همچنین این امکان را دارید تا چندین متغیری را که در یک بیانیه (statement) معرفی شده اند، مقدار دهی اولیه کنید :

int a = 5, b = 6;
int c(7), d(8);
int e{9}, f{10};

معمولاً وقتی که برنامه نویسان جدیدتر چندین متغیر را در یک خط تعریف می کنند، محتمل است که سه اشتباه را انجام بدهند.

اشتباه اول اینست که به هر متغیر یک نوع داده (data type) می دهند. البته این اشتباه زیاد بدی نیست و کامپایلر در این زمینه به شما هشدار می دهد.

int a, int b; // wrong (compiler error)

int a, b; // correct

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

int a, double b; // wrong (compiler error)

int a; double b; // correct (but not recommended)

// correct and recommended (easier to read)
int a;
double b;

اشتباه آخر خطرناک است. در این مورد، برنامه نویس به اشتباه سعی می کند تا هر دو متغیر را با یک مقدار اولیه، مقدار دهی کند :

int a, b = 5; // wrong (a is uninitialized!)

int a= 5, b= 5; // correct

در بیانیه اول از مثال بالا، متغیر a بدون مقدار اولیه (uninitialized) باقی می ماند، و کامپایلر هم شکایتی از این بابت نخواهد کرد. در این مورد اگر تصور برنامه نویس این باشد که متغیر a مقدار اولیه گرفته است، برنامه اش کرش خواهد کرد و یا اینکه نتایج نادرستی را نمایش خواهد داد که وضعیت خطرناکی می باشد.

بهترین راه برای اینکه از این اشتباه جلوگیری کنیم، اینست که روش مقدار دهی اولیه بر اساس direct initialization و یا روش Uniform initialization را به خاطر بسپارید :

int a, b(5);
int c, d{5};

در این روش، واضح تر است که مقدار 5 تنها به متغیر b منتسب شده است و متغیر a بدون مقدار اولیه باقی مانده است.

از آنجا که معرفی متغیرها در یک خط ممکن است در مقدار دهی اولیه آنها شما را به اشتباه بیندازد، توصیه ما اینست که در مواردی که می خواهید متغیرها دارای مقدار اولیه باشند آنها را در بیانیه های (statements) جداگانه معرفی کنید و فقط در صورتی که می خواهید چندین متغیر را بدون مقدار اولیه معرفی کنید از روش معرفی چندین متغیر در یک بیانیه بهره ببرید. این روش امکان اشتباه را کاهش می دهد و در ضمن خوانایی کدهای شما را نیز بالاتر می برد.

قانون : اگر می خواهید متغیرهای شما دارای مقدار اولیه باشند آنها را در یک بیانیه معرفی نکنید.

متغیرها را کجا معرفی کنیم؟


کامپایلرهای قدیمی تر زبان C کاربران را مجبور می کردند تا تمامی متغیرهای یک تابع را در ابتدای تابع معرفی کنند :

int main()
{
// all variable up top
int x;
int y;

// then code
std::cout << "Enter a number: ";
std::cin >> x;

std::cout << "Enter another number: ";
std::cin >> y;

std::cout << "The sum is: " << x + y << std::endl;
return 0;
}

این سبک در حال حاضر منسوخ شده است. کامپایلر ++C شما را ملزم نمی کند تا تمامی متغیرها را در بالای تابع معرفی کنید. سبک صحیح ++C اینست که متغیرها را در نزدیکترین محلی که از آنها استفاده خواهید کرد معرفی نمایید :

int main()
{
std::cout << "Enter a number: ";
int x; // we need x on the next line, so we'll declare it here, as close to its first use as we reasonably can.
std::cin >> x; // first use of x

std::cout << "Enter another number: ";
int y; // we don't need y until now, so it gets declared here
std::cin >> y; // first use of y

std::cout << "The sum is: " << x + y << std::endl;
return 0;
}

این روش چندین مزیت دارد.

اول اینکه، متغیرها تنها در زمانی که مورد نیاز هستند، تعریف می شوند، همچنین بیانیه های بعد از آنها به نوعی کاربرد آنها را واضحتر نشان می دهد. به عنوان مثال، اگر ما متغیر x را در بالای تابعی معرفی کنیم تا زمانیکه در کد به کاربرد آن نرسیم هیچ ایده ای در مورد اینکه x چه می باشد و چه کاری را انجام می دهد، نخواهیم داشت و به ناچار باید کد را کامل رصد کنیم تا به موارد استفاده متغیر x برسیم. حالا اگر همین متغیر x را مثلاً در کنار یک سری بیانیه (statement) که مربوط به بیانیه های ورودی و خروجی (input/output statements) معرفی کنیم، برای ما روشن می شود که متغیر x به عنوان ورودی یا خروجی در جای خاصی مورد استفاده قرار گرفته است.

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

نکته آخر اینکه، احتمال اینکه یک متغیر بدون مقدار اولیه (Uninitialized) بماند، کاهش می یابد، چرا که همزمان با معرفی آن متغیر از آن استفاده می کنیم و فوراً آن را مقدار دهی خواهیم کرد.

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

قانون : تا جایی که می توانید متغیرها را در نزدیکترین محل استفاده از آنها معرفی کنید.


آموزش قبلی : آموزش زبان ++C : اشکال زدایی (Debugging) برنامه ها قسمت دوم

آموزش بعدی : آموزش زبان ++C : نوع داده Void



نمایش دیدگاه ها (0 دیدگاه)

دیدگاه خود را ثبت کنید:

انتخاب تصویر ویرایش حذف
توجه! حداکثر حجم مجاز برای تصویر 500 کیلوبایت می باشد.