یه ثابت عددی مثل 1234 یه مقدار از نوع int هست.
اگه بخوایم یه عدد از نوع long بنویسیم، باید آخرش یه l یا L اضافه کنیم، مثلاً:
123456789L
همچنین، اگه یه عدد اونقدر بزرگ باشه که توی int جا نشه، کامپایلر خودش اون رو به long تبدیل میکنه.
برای تعریف عددهای بدون علامت (unsigned) هم از پسوند u یا U استفاده میکنیم،
و ترکیب ul یا UL یعنی اون عدد unsigned long هست.
عددهای اعشاری (floating-point constants) یا یه نقطهی اعشاری دارن (123.4)، یا یه توان (exponent) مثل 1e-2، یا هر دو.
نوعشون بهصورت پیشفرض double هست،
مگر اینکه با پسوند مشخص کنیم:
-
پسوند f یا F → عدد از نوع float
-
پسوند l یا L → عدد از نوع long double
مقدار یه عدد صحیح رو میتونیم بهجای مبنای دهدهی (decimal)، توی مبنای هشت (octal) یا شانزده (hexadecimal) هم بنویسیم.
-
اگه عدد با 0 شروع بشه → یعنی عدد به مبنای هشت نوشته شده.
-
اگه با 0x یا 0X شروع بشه → یعنی مبنای شانزده.
مثلاً عدد دهدهی ۳۱ رو میشه اینطوری نوشت:
037 (به مبنای هشت) یا 0x1f و 0x1F (به مبنای شانزده).
اعداد هشتپایه و شانزدهپایه هم میتونن با L (برای long) و U (برای unsigned) ترکیب بشن، مثلاً:
0XFUL → یعنی یه unsigned long با مقدار ۱۵ دهدهی.
یه ثابت کاراکتری (character constant) در واقع یه عدد صحیح هست که با یه کاراکتر داخل کوتیشن تکی نوشته میشه، مثل 'x'.
مقدارش هم عدد معادل اون کاراکتر توی جدول کاراکترهای سیستم هست.
مثلاً توی جدول ASCII، کاراکتر '0' مقدار عددی ۴۸ داره —
که هیچ ربطی به عدد ۰ واقعی نداره!
برای همین بهتره توی برنامههامون بهجای نوشتن ۴۸، بنویسیم '0' تا برنامهمون مستقل از نوع جدول کاراکتر باشه و خواناتر هم بشه.
کاراکترها درست مثل عددهای دیگه میتونن توی عملیات عددی شرکت کنن،
ولی معمولاً برای مقایسه بین کاراکترها استفاده میشن.
بعضی کاراکترها رو نمیشه مستقیم نوشت،
برای همین از توالیهای فرار (escape sequences) استفاده میکنیم، مثل \n (برای newline).
این توالیها ظاهراً دو کاراکترن، ولی در واقع فقط یه کاراکتر خاص رو نشون میدن.
همچنین میتونیم یه الگوی باینری دلخواه (به اندازهی یه بایت) رو با استفاده از عددهای هشتپایه یا شانزدهپایه بنویسیم:
'\ooo' // که ooo عددی بین 0 تا 7 هست (هشتپایه)
'\xhh' // که hh عددی در مبنای شانزده هست (0-9, a-f, A-F)
مثلاً میتونیم بنویسیم:
#define VTAB '\013' /* تب عمودی در ASCII */
#define BELL '\007' /* صدای زنگ در ASCII */
یا به صورت شانزدهپایه:
#define VTAB '\xb' /* تب عمودی در ASCII */
#define BELL '\x7' /* صدای زنگ در ASCII */
لیست کامل توالیهای فرار (Escape Sequences):
| توالی | معنی |
|---|---|
| \a | صدای زنگ (alert) |
| \b | backspace |
| \f | formfeed |
| \n | newline |
| \r | carriage return |
| \t | tab افقی |
| \v | tab عمودی |
| \\ | بکاسلش \ |
| \? | علامت سؤال ? |
| \' | کوتیشن تکی ' |
| \" | کوتیشن دوتایی " |
| \ooo | عدد هشتپایه |
| \xhh | عدد شانزدهپایه |
کاراکتر '\\0' نمایانگر کاراکتری با مقدار صفره — بهش میگیم کاراکتر null.
گاهی '\\0' رو بهجای 0 مینویسن تا نشون بدن منظورشون کاراکتر صفره نه عدد صفر.
یه عبارت ثابت (constant expression) عبارتیه که فقط از ثابتها تشکیل شده.
کامپایلر این عبارتها رو در زمان کامپایل محاسبه میکنه، نه موقع اجرا.
برای همین میتونیم ازشون هرجا که یه مقدار ثابت لازمه استفاده کنیم، مثلاً:
#define MAXLINE 1000
char line[MAXLINE + 1];
یا
#define LEAP 1 /* در سالهای کبیسه */
int days[31 + 28 + LEAP + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31];
یه رشتهی ثابت (string constant) یا string literal،
دنبالهای از صفر یا چند کاراکتره که بین کوتیشن دوتایی " " قرار میگیره، مثلاً:
"I am a string"
یا
"" /* رشتهی خالی */
کوتیشنها خودشون جزو رشته نیستن — فقط برای مشخص کردن ابتدا و انتهاش هستن.
توی رشتهها هم همون توالیهای فرار کار میکنن؛ مثلاً \" برای نوشتن کاراکتر ".
چند رشته رو میتونیم موقع کامپایل بهصورت خودکار به هم بچسبونیم:
"hello, " "world"
معادل با اینه:
"hello, world"
این ویژگی خیلی به درد میخوره وقتی رشتهمون طولانیه و نمیخوایم یه خط خیلی بلند توی کدمون داشته باشیم.
از نظر فنی، یه رشته در C در واقع یه آرایه از کاراکترهاست.
در انتهای هر رشته یه کاراکتر '\0' وجود داره تا پایانش مشخص بشه.
پس تعداد بایتهایی که واقعاً ذخیره میشه، یکی بیشتر از تعداد کاراکترهاییه که بین کوتیشنها نوشتیم.
بهخاطر همین ساختار، هیچ محدودیتی روی طول رشته وجود نداره،
ولی برای بهدست آوردن طول رشته باید تا '\0' رو بخونیم.
تابع استاندارد strlen(s) طول رشتهی s رو (بهجز '\0') برمیگردونه.
نسخهی خودمون از این تابع به شکل زیره:
/* strlen: برگردوندن طول رشته */
int strlen(char s[])
{
int i;
while (s[i] != '\0')
++i;
return i;
}
تابع strlen و بقیهی توابع کار با رشته توی فایل سرآیند <string.h> تعریف شدن.
یه نکتهی مهم
بین 'x' و "x" تفاوت وجود داره!
'x' یه عدد صحیحه (مقدار عددی کاراکتر x)،
ولی "x" یه رشتهست که از دو کاراکتر تشکیل شده: 'x' و '\0'.
یه نوع دیگه از ثابتها هم داریم به نام ثابتهای شمارشی (enumeration constants).
یه enumeration یا enum، لیستی از مقدارهای عددی ثابته، مثلاً:
enum boolean { NO, YES };
اولین نام مقدار ۰ داره، بعدی ۱، و به همین ترتیب.
مگر اینکه خودمون مقدار خاصی براشون مشخص کنیم.
اگه فقط برای بعضیا مقدار بذاریم، بقیه بهترتیب ادامه پیدا میکنن، مثلاً:
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t',
NEWLINE = '\n', VTAB = '\v', RETURN = '\r' };
enum months { JAN = 1, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC };
/* یعنی FEB = 2، MAR = 3 و ... */
اسمهای داخل enumerationهای مختلف نباید تکراری باشن،
ولی داخل یه enumeration میتونن مقادیر تکراری داشته باشن.
enumeration یه روش راحت برای دادن نام به مقدارهای ثابت هست،
مشابه #define ولی با این مزیت که مقدارها بهصورت خودکار برات ساخته میشن.
هرچند میتونیم متغیر از نوع enum تعریف کنیم،
اما کامپایلر الزاماً چک نمیکنه مقدارش حتماً یکی از اون مقدارهای تعریفشده باشه.
با این حال، استفاده از enum معمولاً بهتر از #define هست،
چون بعضی از دیباگرها (debugger) میتونن مقدار enum رو بهصورت اسمش نشون بدن، نه عددش