PDA

View Full Version : نحوه تعریف متغییر جدید و 8 بیتی در ++C/C



md3848
دوشنبه 17 اسفند 1394, 09:51 صبح
سلام
من با میکرو ها کار میکنم، تو کامپیایلر آردوینو یه نوع متغییر 8 بیتی از نوع صحیح هستش با نام byte ولی تو کامپایلر کدویژن همچین متغییری نیستش که هم 8 بیتی باشه و هم از نوع صحیح، این کامپایلر آردوینو برمبنای ++C هستش و این کدویژن برمبنای C هستش، حالا خاستم ببینیم متغییر 8 بیتی و صحیح فقط مختص زبان ++C هستش یا این که خودم میتونم یه همچین متغییری رو بسازم؟:متفکر:

چون من 98 تا متغییر 8 بیتی میخوام تو برنامم و اگه بخوام از متغییر های 16 بیتی استفاده کنم حجم برنامم الکی گرفته میشه، مخصوصا این که با کمبود فضا مواجه هم هستم(چون حافظه میکرو ها کم و محدود هستش:گریه:)




طی مطالعاتی!!! که داشتم مثل این که با enum میشه این کار رو کرد، حالا تعریف این نو از متغییر به روش زیر درسته؟

enum int8bit{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1 7,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33, 34,35,36,37,
38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54 ,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,7 1,72,
73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89 ,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104 ,105,
106,107,108,109,110,111,112,113,114,115,116,117,11 8,119,120,121,122,123,124,125,126,127,128,129,130, 131,
132,133,134,135,136,137,138,139,140,141,142,143,14 4,145,146,147,148,149,150,151,152,153,154,155,156, 157,
158,159,160,161,162,163,164,165,166,167,168,169,17 0,171,172,173,174,175,176,177,178,179,180,181,182, 183,
184,185,186,187,188,189,190,191,192,193,194,195,19 6,197,198,199,200,201,202,203,204,205,206,207,208, 209,
210,211,212,213,214,215,216,217,218,219,220,221,22 2,223,224,225,226,227,228,229,230,231,232,233,234, 235,
236,237,238,239,240,241,242,243,244,245,246,247,24 8,249,250,251,252,253,254,255};

Ananas
سه شنبه 18 اسفند 1394, 14:56 عصر
سلام.
خب char عدد صحیح هشت بیتیه. تو فایل cstdint.h چند نوع مفید تعریف شده که اسمشون سایزشون رو به همراه داره:
int8_t
int16_t
int32_t
int64_t
uint8_t
uint16_t
uint32_t
uint64_t

md3848
سه شنبه 18 اسفند 1394, 16:17 عصر
ممنون از شما
میشه این فایل کتابخونه رو برام بفرستید
چون کامپایلری که من استفاده میکنم برا میکرو کنترلر ها هستش و این کتابخونه رو نداره؛ و در ضمن نحوه تعریف کردن یه متغییر Int جدید به چه صورت هستش؟

حامد مصافی
چهارشنبه 19 اسفند 1394, 06:49 صبح
همونطوری که دوستمون فرمودند نیاز به چیز دیگری نیست. از نوع char استفاده کنید.

md3848
چهارشنبه 19 اسفند 1394, 08:17 صبح
خب CHAR یه متغییر از نوع کاراکتری هستش که کد اسکی داخل خودش ذخیره میکنه و نه عدد صحیح
هر چند که 8 بیتی هستش و کد اسکی های 0 تا 255 رو داخل خودش ذخیره میکنه ولی کد اسکی هستش و نه عدد صحیح
البته میشه ازش به عنوان یه متغییر INT هشت بیتی استفاده کرد ولی باس یه سری کار اضافه انجام بدیم....مثال زیر رو ببینید
این که همش هنگام فراخونی متغییر های از نوع char بخوان یه (int) پشت سر اون متغییر قرار بدیم زیاد جالب نیست، و ممکنه خطاهایی رخ بده و باگ گیری در این حالت یکم سخت میشه
راحی برا حل این مشکل وجود نداره؟:متفکر: که دیگه مجبور نباشیم از (int) استفاده کنیم؟
در ضمن این که میکرو بیاد و این کد اسکی رو به عدد صحیح تبدیل کنه همین کلاک مصرف میکنه و باعث کاهش سرعت اجرای برنامه میشه.....
کلا این متغییر های 16 بیتی به بالا رو بر مبنای همین متغییر های Char ساختن؟؟؟


#include <iostream>
using namespace std;

int main()
{
int A = 48;
char B = 48; // 0

cout << A << " , " << (int)B;

while(1);
}

حامد مصافی
چهارشنبه 19 اسفند 1394, 12:34 عصر
متغیر نوع کاراکتری چیه دیگه؟ همه چیز در کامپیوتر صفر و یک هستند. char نوع داده‌ای است که توانایی ذخیره‌سازی ۸ بیت را دارد. عمده کاربرد اون هم ذخیره سازی کاراکتر‌های اسکی است چون این کاراکتر‌ها هم در ۸ بیت ذخیره می‌شود. توجه کن که مقدار عددی کاراکتری در این نوع داده ذخیره میشه.



هر چند که 8 بیتی هستش و کد اسکی های 0 تا 255 رو داخل خودش ذخیره میکنه ولی کد اسکی هستش و نه عدد صحیح
دقیقاً عدد صحیح در اون ذخیره میشه

#include <iostream>
using namespace std;

char add(char n1, char n2)
{
return n1 + n2;
}


int main()
{
char a = 10;
char b = 54;


char c = add(a, b);

while(1);
}

md3848
چهارشنبه 19 اسفند 1394, 14:22 عصر
خب حرف شما قبول، ولی در کل باید (int) رو حتما قرار داد....مثال زیر رو ببینید
و در ضمن اگه اشتب نکنم نوع char اعداد -127 تا 128 رو پشتیبانی میکنه و نوع unsigned char اعداد 0 تا 255 رو - پس باید برای متغییر 1 بایتی int از نوع unsigned int استفاده کرد.

#include <iostream>
using namespace std;

int main()
{
int A = 48;
char B = 50; //

//cout << B; // اشتباه
cout << (int)B << "\n"; // درست

B = A + 5;
//cout << B; // اشتباه
cout << (int)B << "\n";

while(1);
}




یه سوال دیگه : چون این کتابخونه ای که من میخوام بنویسیم میخوام هم تو کامپایلر آردوینو و هم در کامپایلر کدویژن(و انشاالله در تموم کامپایلر ها) قابل اجرا باشه ولی این دو کامپایلر تو بعضی چیزا فرق دارن با هم، مثلا نام متغییر 8 بیتی در آردوینو byte هستش و در کدویژن char هستش،

من نوع متغییر int هشت بیتی در کتابخونم رو uint8 تعریف میکنم

حالا میخوام کدی رو بنویسم که اگه کامپایلرش آردوینو بود بیاد و به کمک typedef نام متغییر byte رو به uint8 تغییر بده
و اگه کامپایلرش کدویژن بود و بیاد char رو به uint8 تغییر نام بده
این کار شدنی هستش؟ کدش به چه صورت میشه؟

Ananas
چهارشنبه 19 اسفند 1394, 17:02 عصر
ببینید همونطور که آقا مصافی فرمودن همه چیز تو کامپیوتر صفر و یکه و کلا همه چیز رو با ترکیب صفر و یک ها شبیه سازی میکنیم. تو کامپیوتر و برنامه نویسی چند نوع پایه ای وجود داره که تو اکثر زبانهای برنامه نویسی هست. چون مربوط به نحوه ی کار رم و سی پیو میشه. اطلاعات بیتی تو بسته های 8 تایی ذخیره میشن و این کوچک ترین پکی هست که میشه به شکل یک متغیر تعریف کرد. البته میشه به هر هشت بیت داخلش به راحتی دسترسی داشت و تغییرش داد و یا بازخونی کرد. از کنار هم گذاشتن دو تا هشت بیت یک متغیر 16 و از کنار هم گذاشتن دو تا 16 یک 32 بیتی و از دوتا 32 یک 64 بیتی داریم. پس انواع پایه در کامپیوتر یا 8 یا 16 یا 32 یا 64 بیتی هستن. و معمولا به شکل عدد صحیح تفسیر میشن. حالا یا با علامت یا بدون علامت. و سه نوع اعشاری هم هست که اعشاریه 32 بیتی و اعشاری 64 بیتی و اعشاری 80 بیتی (80 بیتی همیشه در دسترس نیست). باقیه انواع از باز تعریف یا کنار هم قرار دادن این چند نوع به وجود میان.
نوع char در cpp همون نوع هشت بیتیه پایه هست که چون بیشترین استفاده برای کاراکتر های حروف از این هشت بیتی بوده اینطور اسمشو گذاشتن. ینی character. و چیزی نیست جز مجموعه ای از بیتها و بنا به قرار داد جهانیه کدهای اسکی میان اون بیتهارو به شکل حروف تفسیر میکنن. شما میتونید هر طور که برنامتون نیاز داره تفسیر کنید. لازم نیست تبدیل بشه. اینکه پشت یک نوع char عبارت تبدیل کردن به int رو میگذاریم در واقع داریم دوتا کار انجام میدیم...
1- اینکه به کامپایلر میگیم که اون رو به شکل یک عدد تفسیر کن نه حرف
2- اینکه به کامپایلر میگیم که این هشت بیت رو برامون تو این مرحله از محاسبات بریز داخل یک متغیر 32 بیتی(int نوعیه که بیتش ثابت نیست. ممکنه 16 بیتی یا 64 بیتی باشه. ولی انواع دیگه که جزو لغات کلیدی cpp هستن سایزشون ثابته مثل long ). پس میتونیم اینطور بهش نگاه کنیم که با این دستور کامپیوتر میاد یک عدد 8 بیتی رو میریزه تو یک متغیر 32 بیتی و برمیگردونه.
حالا بعضی از توابع هستند که ورودیه اونها char یا آرایه ای از char هست و داخل تابع اون char یا آرایه ای از char را به عنوان کاراکتر های حروف انگلیسی تفسیر میکنه. میتونستن تابع رو جوری تعریف کنن که اون رو به شکل یک عدد صحیح 8 بیتی تفسیر کنه.
پس شما به char به عنوان یک عدد صحیح هشت بیتی نگاه کن که به طور پیشفرض در داخل کدها و اکثر توابع اون رو به شکل کاراکتر حروف تفسیر میکنن. ولی الزامی نداره. و حتی عباراتی که داخل '' قرار میدید مثل 'm' رو هم میتونید به شکل یک عدد ببینید! ینی همون کد اسکی ای که حرف m کوچک داره. ینی عملیاتی که با اعداد انجام میدید میتونید با این لیترال ها انجام بدید. مثلا :



char x = 'a' + 'A';












اگر شما سعی کنید که یک نوع شمارشی یا همون enumerate تعریف کنید که تعداد بیتهاش رند به 8 نباشه حداقل بایتهای 8 بیتی ای که میشه گذاشت تا اون تعداد بیت رو داشته باشه میشه سایز نوعتون. ینی اگر سعی کنید که 15 بیت تعریف کنید کامپایلر میاد 16 بیت میده و از 15 بیتش استفاده میکنه. پس 8 کوچکترین پکه.
مطالبی که نوشتم تجربی یاد گرفتم و ممکنه بعضی قسمتاش اشتباه باشه. دوستانی که ایرادی میبینن لطفا درستش رو بفرمایند.

Ananas
چهارشنبه 19 اسفند 1394, 17:18 عصر
حالا میخوام کدی رو بنویسم که اگه کامپایلرش آردوینو بود بیاد و به کمک typedef نام متغییر byte رو به uint8 تغییر بده
و اگه کامپایلرش کدویژن بود و بیاد char رو به uint8 تغییر نام بده
این کار شدنی هستش؟ کدش به چه صورت میشه؟
اگر کامپایلرهایی که استفاده میکنید از c یا c++ استاندارد پشتیبانی کنن این فایلی که گفتم رو باید داشته باشن. فایل stdint.h و یا cstdint . تو کامپایلر من cstdint رو بدون .h باید بنویسم. و تو اون این چند نوع که گفتم تعریف شده و جزو استاندار c++ هست. به سایت cplusplus.com مراجعه کنید و جستجو کنید پیدا میکنید اینارو.
بعد هم char نوعی هست که تو خود cpp هست و جزو لغات کلیدیه این زبانه. بعید میدونم که نداشته باشن. شما تو همشون از char استفاده کنی میشناسن.
ولی اگر خاستید با استفاده از یک شرط چیزی رو بنویسید و یا ننویسید باید از مکروها استفاده کنید. مثال:

#ifdef __BORLANDC__
typedef char MyInt;
#else
typedef short MyInt;
#endif

کد بالا اگر در کامپایلر برلند کامپایل بشه نوع MyInt یک بایت هست وگرنه دوبایت حجم داره.

md3848
پنج شنبه 20 اسفند 1394, 04:16 صبح
عد هم char نوعی هست که تو خود cpp هست و جزو لغات کلیدیه این زبانه. بعید میدونم که نداشته باشن. شما تو همشون از char استفاده کنی میشناسن.

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



الان این کد به صورت خودکار خودش تشخیص میده نوع کامپایلر رو؟ یا من باید در برنامم(و نه کتابخونه) چیزی بنویسم؟(این کد شما در کتابخونه قرار میگیره)

اگه خودش تشخیص میده به صورت خودکار این نام کامپایلر رو بزارم حله یا استاندارد مستاندارد خاصی داره و یا باید برم منو آلش! رو بخونم و این اسمش رو پیدا کنم و در کد بالا بزارم؟:لبخند:

Ananas
پنج شنبه 20 اسفند 1394, 15:09 عصر
این عبارت شرطی که به شکل مکرو نوشته شده که جزو زبان cpp ه فقط اون __BORLANDC__ چیزی هست که تو کامپایلر برلند تعریف و معرفی میشه و برای این هست که در برنامه بشه تشخیص داد که کامپایلر برلنده یا نه. برای کامپایلر های دیگه باید به رفرنسش مراجعه کنید و ببینید که چه عبارتی براشون تعریف میشه و میشه باهاش تشخیص داد که اون کامپایلر داره کامپایل میکنه. اگر یک عبارتی با define به شکل مکرو تعریف نشده باشه ناشناخته هست. کد هیچ اشکالی براش پیش نمیاد ولی قسمت if اجرا نمیشه و میره تو else البته اگر else داشته باشه. مثلا کد زیر همیشه قسمت else اجرا میشه نه if :

#if 0
//...
//...
//...
#else
//...
//...
//...
#endif

مکروها در واقع دستوراتی هستند که ما به کامپایلر میدیم. دستورات برنامه نیستند. ینی در زمان کامپایل برسی میشن و تمام. در زمان اجرای برنامه کاری انجام نمیدن. ینی اگر شرطی هم گذاشته شده یکبار میسنجه موقع کامپایل و بعد موقع اجرا دیگه همیشه همون چیزی که اول نتیجه گرفت رو انجام میده.