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


آموزش زبان ++C : متغیرهای integer با عرض ثابت و مبحث متغیرهای بدون علامت

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

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



چرا اندازه متغیرهای integer ثابت نمی باشد؟


پاسخ کوتاه و غیر فنی اینست که این مساله به زبان C که منشاء زبان ++C می باشد، باز می گردد. در زبان C کارآیی مهمترین نگرانی بود. زبان C تعمداً اندازه متغیرهای integer را باز گذاشت تا کامپایلرها با توجه به معماری کامپیوتر هدف، خودشان بتوانند بهترین اندازه مناسب را انتخاب کنند.

آیا این احمقانه نیست؟


بله همینطور است! به عنوان یک برنامه نویس، این مساله کمی مضحک است که با متغیرهایی سر و کار داشته باشیم که اندازه آنها بسته به معماری کامپیوتر هدف، متفاوت باشد.

متغیرهای integer با عرض ثابت


برای کمک به قابلیت انتقال برنامه ها روی پلتفرم های مختلف، در استاندارد C99 مجموعه ای از متغیرهای integer با عرض ثابت معرفی شده اند (که در هدر stdint.h قرار دارند) که تضمین می کنند در هر معماری اندازه آنها یکسان باقی بماند.

این متغیرهای integer با اندازه ثابت، به شرح زیر می باشند :

آموزش زبان ++C : متغیرهای integer با عرض ثابت و مبحث متغیرهای بدون علامت
در زبان ++C نسخه 11 این متغیرهای integer با اندازه ثابت، به طور رسمی بخشی از زبان ++C شدند. شما می توانید با افزودن هدر cstdint از آنها استفاده کنید، این هدر این متغیرها را در فضای نامی std در اختیار شما قرار می دهد. در ادامه مثالی را آورده ایم :

#include "iostream"
#include "cstdint"

int main()
{
std::int16_t i(5); // direct initialization
std::cout << i;
return 0;
}

با وجودیکه این متغیرها تا زمان C++11 هنوز تصویب نشده بودند، اما بخشی از استاندارد C99 می باشند، برخی از کامپایلرهای قدیمی تر ++C این نوع متغیرها را در هدر stdint.h ارائه می دهند. در کامپایلر ویژوال استودیو 2005 و همینطور 2008 هدر stdint.h وجود ندارد، اما در نسخه 2010 و نسخه های بعدی این هدر اضافه شده است.

اگر در کامپایلر شما فایل های cstdint یا stdint.h وجود نداشته باشد، خبر خوب اینست که شما می توانید فایل pstdint.h را که توسط Paul Hsieh طراحی شده است و با پلتفرم های مختلف سازگار می باشد را دانلود کنید. کافیست به سادگی هر چه تمامتر فایل pstdint.h را در داخل پروژه خود قرار بدهید و سپس می توانید متغیرهای integer با اندازه ثابت را معرفی کنید.

هشدار : انواع داده های int8_t و uint8_t ممکن است مانند انواع داده char رفتار کنند


با توجه به یک اشتباه نظری در مشخصات ++C ، برخی از کامپایلرها با انواع داده های int8_t و uint8_t به ترتیب همانند انواع داده های signed char و unsigned char برخورد می کنند، اما این ضروری نیست. در نتیجه، std::cin و std::cout ممکن است آنطور که شما انتظار دارید کار نکنند. در ادامه در مثالی این مورد را آورده ایم :

#include "iostream"
#include "cstdint"

int main()
{
int8_t myint = 65;
std::cout << myint;

return 0;
}

در اکثر سیستمها این برنامه کاراکتر A را چاپ می کند (در واقع با متغیر myint به عنوان یک char برخورد می شود). با این حال، در برخی سیستمها همانطور که انتظار دارید عدد 65 چاپ خواهد شد.

برای سادگی، بهتر است تا از انواع داده های int8_t و uint8_t استفاده نکنید و به جای آنها از انواع int16_t و uint16_t استفاده کنید. با این حال، اگر از int8_t و uint8_t استفاده کردید، باید مراقب باشید تا توابع دیگر با آنها مانند integer برخورد کنند و نه مانند char (این موضوع مخصوصاً در مورد std::cout و std:cin صدق می کند).

امیدواریم که در آینده ++C این مساله را روشن سازد و از این ابهام جلوگیری کند.

قانون : از انواع داده های int8_t و uint8_t استفاده نکنید و به جای آنها از انواع int16_t و uint16_t استفاده کنید.

جنبه های منفی متغیرهای integer با اندازه ثابت


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

سریع و حداقلی


برای کمک به رفع جنبه های منفی مورد اشاره، در C++11 دو مجموعه از متغیرهای integer با اندازه ثابت به عنوان جایگزین ارائه شده اند.

نوع سریع int_fast#_t به شما یک متغیر integer می دهد که بسیار سریع عمل می کند. به جای علامت # مقادیر 8 یا 16 یا 32 و یا 64 بیت قرار می گیرند. به عنوان مثال int_fast32_t سریعترین نوع integer از نوع 32 بیتی را به شما ارائه می کند.

نوع داده حداقلی int_least#_t به شما کوچکترین نوع داده integer را می دهد. به جای علامت # مقادیر 8 یا 16 یا 32 و یا 64 بیت قرار می گیرند. به عنوان مثال، int_least32_t کوچکترین متغیر integer از نوع 32 بیتی را به شما ارائه می دهد.

بهترین روش استفاده از integer


با توجه به اینکه متغیرهای integer با اندازه ثابت به زبان ++C اضافه شده اند، بهترین شیوه استفاده از متغیرهای integer به شرح زیر می باشند :

  • اگر اندازه ثابت متغیر برای شما مهم نباشد ترجیح شما بر این باشد که از int استفاده کنید. برای مثال، اگر از کاربر می خواهید تا سنش را وارد کند یا اگر می خواهید از 1 تا 10 را در برنامه بشمرید، مهم نیست که متغیر شما 16 بیتی یا 32 بیتی باشد، در هر صورت این اعداد در آن جا می گیرد. این مساله اکثریت قریب به اتفاق موارد استفاده شما را می تواند تحت پوشش قرار دهد.
  • اگر شما می خواهید متغیر شما اندازه ثابتی را تضمین کند و کارآیی نیز برای شما مهم می باشد، از int_fast#_t استفاده کنید.
  • اگر می خواهید متغیر شما اندازه ثابتی را تضمین کند و مهمتر از کارآیی برای شما میزان حافظه مورد استفاده می باشد از int_least#_t استفاده کنید. این گزینه مخصوصاً در مواقعی که می خواهید تعداد زیادی متغیر معرفی کنید مفید می باشد.
  • از متغیرهای از نوع unsigned (بدون علامت) تنها در مواقعی استفاده کنید که دلیل قانع کننده ای داشته باشید.

برخی کامپایلرها نسخه اختصاصی خودشان را از متغیرهای integer با اندازه ثابت ارائه داده اند. به عنوان مثال در ویژوال استودیو انواع __int8 و __int16 و ... ارائه شده اند. به هیچ وجه از این طاعون ها استفاده نکنید و در دامشان نیفتید.

بحث در مورد اعداد بدون علامت (unsigned numbers)


خیلی از برنامه نویسان (مخصوصاً بعضی از خانه های برنامه نویسی بزرگ مانند گوگل) باور دارند که به طور کلی باید از استفاده از متغیرهای بدون علامت (unsigned integers) پرهیز کرد. این مساله مخصوصاً در مواقعی که بخواهید متغیرهای signed و unsigned را با هم ترکیب کنید، منجر به نتایج غیر منتظره ای می گردد.

قطعه کد زیر را در نظر بگیرید :

void doSomething(unsigned int x)
{
// Run some code x times
}

int main()
{
doSomething(-1);
}

در این مورد چه اتفاقی خواهد افتاد؟ عدد -1 به اعداد بزرگی تبدیل می شود (شاید 4294967295)، و برنامه شما مثل یک موشک بالستیک عمل می کند. اما حتی بدتر از آن اینست که هیچ راه خوبی برای پیشگیری این وضعیت وجود ندارد. زبان ++C به صورت آزادانه عملیات تبدیل بین اعداد علامت دار و بدون علامت را انجام می دهد، اما هیچ نوع کنترلی بر روی محدوده مجاز متغیرها نمی کند تا از خطای سر ریز (overflow) جلوگیری گردد.

خیلی از زبانهای برنامه نویسی مدرن مانند جاوا و سی شارپ متغیرهای بدون علامت را ارائه نداده اند و یا اینکه استفاده از آنها را محدود کرده اند. طراح زبان ++C بیارنه استراستوروپ (Bjarne Stroustrup) گفته است : "استفاده از متغیرهای بدون علامت (unsigned) به جای استفاده از int برای اینکه یک بیت اطلاعات بیشتر را بتوانیم در آن جا بدهیم، هر گز ایده خوبی نبوده است".

این بدین معنا نمی باشد که شما نباید از متغیرهای بدون علامت (unsigned) استفاده کنید، اما اگر از آنها استفاده می کنید، واقعاً در مواردی که مطمئن هستید مشکلی ایجاد نمی شود این کار را انجام بدهید و همینطور مراقب ترکیب متغیرهای علامت دار و بدون علامت باشید.


آموزش قبلی : آموزش زبان ++C : نوع داده Integer

آموزش بعدی : آموزش زبان ++C : اعداد ممیز شناور (اعداد اعشاری)



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

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

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