مبانی برنامهسازی — بخش دوم: دادهها و عملگرها (نسخهی Jupyter Notebook)¶
این نوتبوک دو بخش دارد:
نمای کامل (عین فایل HTML): سلول بعدی خود فایل HTML اصلی را با همان رنگها، انیمیشنها، منوی کناری، جستوجو و دکمهی چاپ نمایش میدهد.
نسخهی قابل اجرا: همان محتوا بهصورت سلولهای متنی و سلولهای کد C که تکتک قابل اجرا هستند.
طرز استفاده (Google Colab یا Jupyter):
اول سلول «آمادهسازی» و سپس سلول «نمای کامل» را اجرا کنید.
هر سلول کدی که با
%%cشروع میشود باgccکامپایل و اجرا میشود. اگر برنامه ورودی میخواهد، آن را جلوی%%cبنویسید؛ مثلاً%%c 25\n30یعنی دو خط ورودی «۲۵» و «۳۰».تکهکدهایی که
mainندارند خودکار داخلmainقرار میگیرند. چند نمونهی «غلطنمایی» عمداً فقط نمایشیاند و اجرا نمیشوند.
# آمادهسازی: ثبت دستور %%c برای کامپایل و اجرای کد C
import re, subprocess, tempfile, os
from IPython.core.magic import register_cell_magic
_HEADERS = ("#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <limits.h>\n"
"#include <float.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <math.h>\n#include <stddef.h>\n")
def run_c(code, stdin_text=""):
"""کد C را کامپایل و اجرا میکند. اگر main نداشته باشد، تکهکد را داخل main میگذارد."""
if not re.search(r'\bmain\s*\(', code):
lines = code.split("\n")
top = [l for l in lines if l.lstrip().startswith("#")]
body = [l for l in lines if not l.lstrip().startswith("#")]
code = _HEADERS + "\n".join(top) + "\nint main(void) {\n" + "\n".join(body) + "\nreturn 0;\n}\n"
with tempfile.TemporaryDirectory() as d:
src, exe = os.path.join(d, "prog.c"), os.path.join(d, "prog")
open(src, "w", encoding="utf-8").write(code)
cp = subprocess.run(["gcc", "-Wall", "-Wextra", "-std=c11", src, "-o", exe, "-lm"],
capture_output=True, text=True)
out = ""
if cp.stderr.strip():
out += "--- پیامهای کامپایلر ---\n" + cp.stderr.replace(src, "prog.c") + "\n"
if cp.returncode != 0:
return out + "(کامپایل ناموفق بود)"
try:
rp = subprocess.run([exe], input=stdin_text, capture_output=True, text=True, timeout=5)
out += "--- خروجی برنامه ---\n" + rp.stdout + rp.stderr
if rp.returncode != 0:
out += f"\n(کد خروج: {rp.returncode})"
except subprocess.TimeoutExpired:
out += "(اجرا بعد از ۵ ثانیه متوقف شد)"
return out
@register_cell_magic
def c(line, cell):
"""%%c [ورودی دلخواه برنامه؛ با \\n برای خط جدید]"""
print(run_c(cell, line.encode().decode("unicode_escape")))نمای کامل (عین فایل HTML اصلی)¶
# نمایش کامل فایل HTML اصلی (فشردهشده در همین سلول) با همان ظاهر و انیمیشنها
import base64, zlib, html as _html
from IPython.display import HTML, display
_PAGE_B64 = "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"
_page = zlib.decompress(base64.b64decode(_PAGE_B64)).decode('utf-8')
display(HTML('<iframe srcdoc="' + _html.escape(_page, quote=True) + '" style="width:100%;height:900px;border:1px solid #ccc;border-radius:8px;resize:vertical"></iframe>'))نسخهی قابل اجرا (متن + سلولهای کد C)¶
بخش دوم: دادهها و عملگرها¶
مخاطب: دانشجویان تازهوارد رشته کامپیوتر (بدون پیشنیاز خاص)
راهنمای استفاده برای مدرس: این متن عمداً به تعداد مشخصی جلسه محدود نشده است. بخشهای اصلی برای تدریس پایه طراحی شدهاند و کادرهای «پنجرهی بیشتر»، «برای کنجکاوها» و «نکتهی مهندسی» محتوای تکمیلیاند؛ مدرس میتواند بسته به زمان، سطح کلاس و علاقهی دانشجویان آنها را تدریس کند یا فقط نامشان را مطرح کند تا مسیر تحقیق بعدی برای دانشجو روشن شود.
اهداف یادگیری¶
در پایان این بخش انتظار میرود دانشجو بتواند:
مفهوم نوع داده، متغیر، مقدار و نمایش داده در حافظه را از هم تفکیک کند.
برای یک مسئلهی ساده نوع دادهی مناسب انتخاب کند و محدودیت بازه و دقت آن را توضیح دهد.
ورودی و خروجی قالببندیشده را با
printfوscanfبنویسد و خطاهای رایج آنها را تشخیص دهد.عملگرهای محاسباتی، رابطهای، منطقی، انتسابی و بیتی را بهدرستی بهکار ببرد.
تفاوت
=و==، تفاوت تقسیم صحیح و اعشاری، و اثر اولویت و associativity عملگرها را تحلیل کند.نمونههای سادهی خطاهای syntax / warning / undefined behavior / logic error را از هم تشخیص دهد.
در مواجهه با نتیجهی عجیب، بهجای حدسزدن، نوع داده، تبدیل نوع، هشدار کامپایلر و ترتیب ارزیابی را بررسی کند.
پیشنیاز و پسنیاز مفهومی¶
پیشنیاز: آشنایی مقدماتی با ساختار یک برنامهی C، مفهوم الگوریتم و چرخهی کلی کامپایل/اجرا.
این بخش پایهی مستقیم مباحث بعدی است: شرطها و حلقهها، توابع، آرایهها، رشتهها، اشارهگرها و مدیریت حافظه همگی بر فهم دقیق نوع داده، عملگر و حافظه تکیه دارند.
فصل ۱: متغیرها و انواع داده¶
مقدمه¶
هر برنامهای، در نهایت، کار میکند با داده. برای اینکه کامپیوتر بداند این دادهها را کجا و چطور نگه دارد، از متغیر (Variable) استفاده میکنیم. متغیر را میتوان مثل یک جعبه در نظر گرفت که یک مقدار در آن نگهداری میشود و یک نام دارد که با آن به آن جعبه دسترسی پیدا میکنیم.
%%c
int age = 20;در این خط: int نوع داده است، age نام متغیر، و 20 مقدار اولیهی آن.
سه مفهوم که نباید با هم قاطی شوند: نام، مقدار و محل ذخیره¶
در سطح مقدماتی میگوییم «متغیر مثل جعبه است». این تشبیه مفید است، اما از همین ابتدا بهتر است سه چیز را جدا ببینیم:
نام متغیر (
age) چیزی است که برنامهنویس در کد مینویسد.نوع متغیر (
int) به کامپایلر میگوید این مقدار چگونه تفسیر شود و چه عملیاتهایی روی آن معنادار است.مقدار (
20) محتوای فعلی آن متغیر است؛ در زمان اجرا این مقدار در بخشی از حافظه نگهداری میشود.
پنجرهی بیشتر: چند فصل بعد، با عملگر
&میتوان آدرس یک متغیر را دید و با «اشارهگر» مستقیماً دربارهی آدرسها صحبت کرد. در این بخش فقط کافی است بدانیم متغیر علاوه بر نام و مقدار، در زمان اجرا یک محل ذخیره هم دارد.
Declaration، Initialization و Assignment¶
این سه واژه شبیه هماند اما یکی نیستند:
%%c
int score; // Declaration: معرفی متغیر
int age = 18; // Declaration + Initialization
score = 20; // Assignment: تغییر/تعیین مقدار پس از تعریفاین تفکیک بعداً هنگام خواندن خطاها، کار با const، آرایهها و اشارهگرها بسیار مهم میشود.
۱. انواع داده پایه¶
زبان C چند نوع دادهی پایه دارد که هرکدام برای ذخیرهی نوع خاصی از اطلاعات مناسباند:
| نوع داده | کاربرد | اندازهی معمول (بایت) | مثال |
|---|---|---|---|
int | اعداد صحیح | ۴ | int x = 10; |
long | اعداد صحیح بزرگتر | ۴ یا ۸ | long x = 100000L; |
long long | اعداد صحیح خیلی بزرگ | ۸ | long long x = 10000000000LL; |
float | اعداد اعشاری (دقت کم) | ۴ | float pi = 3.14f; |
double | اعداد اعشاری (دقت بالا) | ۸ | double pi = 3.14159265; |
char | یک کاراکتر | ۱ | char grade = 'A'; |
bool | مقدار درست/غلط (نیاز به #include <stdbool.h>) | ۱ | bool isValid = true; |
نمایش بصری اشغال حافظههر خانه = ۱ بایت = ۸ بیت
۸ بیت → ۱ بایت
اعداد زیر اندازههای معمول روی بسیاری از سیستمهای امروزیاند؛ استاندارد C برای همهی آنها یک اندازهی ثابت را تضمین نمیکند. برای اندازهی واقعی سیستم، sizeof را بررسی کنید.
char1 بایت · 8 بیت
Byte 0
int4 بایت · 32 بیت
Byte 0
Byte 1
Byte 2
Byte 3
float4 بایت · 32 بیت
Byte 0
Byte 1
Byte 2
Byte 3
double8 بایت · 64 بیت
Byte 0
Byte 1
Byte 2
Byte 3
Byte 4
Byte 5
Byte 6
Byte 7
هر مربع کوچک = ۱ بیت هر گروه ۸تایی = ۱ بایت
نکتهی مهم: اندازهی دقیق این نوعها به کامپایلر و سیستمعامل بستگی دارد. برای دیدن اندازهی واقعی روی سیستم خودتان میتوانید از عملگر sizeof استفاده کنید:
یک عدد واقعاً چطور در حافظه ذخیره میشود؟¶
حافظه را میتوان مثل ردیفی از خانههای کوچک دید. هر بیت فقط دو حالت دارد: ۰ یا ۱. هر ۸ بیت کنار هم یک بایت میسازند.
۸ بیت = ۱ بایت
ارزش بیت1286432168421
5دهدهی
00000101
(0×2⁷) + (0×2⁶) + (0×2⁵) + (0×2⁴) + (0×2³) + (1×2²) + (0×2¹) + (1×2⁰)
۴ + ۱ = ۵
13دهدهی
00001101
(0×2⁷) + (0×2⁶) + (0×2⁵) + (0×2⁴) + (1×2³) + (1×2²) + (0×2¹) + (1×2⁰)
۸ + ۴ + ۱ = ۱۳
42دهدهی
00101010
(0×2⁷) + (0×2⁶) + (1×2⁵) + (0×2⁴) + (1×2³) + (0×2²) + (1×2¹) + (0×2⁰)
۳۲ + ۸ + ۲ = ۴۲
255دهدهی
11111111
(1×2⁷) + (1×2⁶) + (1×2⁵) + (1×2⁴) + (1×2³) + (1×2²) + (1×2¹) + (1×2⁰)
۱۲۸ + ۶۴ + ۳۲ + ۱۶ + ۸ + ۴ + ۲ + ۱ = ۲۵۵
مثلاً یک unsigned char با مقدار ۱۳
00001101
هر مربع = ۱ بیتهر ۸ مربع = ۱ بایت00001101₂ = 13₁₀
نکتهی مهم: حافظه «عدد ۱۳» را به شکل نوشتهی «13» نگه نمیدارد؛ داده به الگوی بیتها تبدیل میشود. تفسیر این بیتها به نوع داده بستگی دارد.
مبناهای عددی: یک مقدار، چند شیوهی نوشتن¶
تا اینجا اعداد را با رقمهای ۰ تا ۹ نوشتهایم؛ یعنی در مبنای ۱۰ (دهدهی). اما سختافزار رایانه فقط دو حالت ۰ و ۱ میشناسد، و برنامهنویسها برای خواندن راحتتر الگوی بیتها دو مبنای کمکی هم به کار میبرند: هشتهشتی (Octal) و شانزدهشانزدهی (Hexadecimal، بهاختصار «هگز»).
نکتهی کلیدی این است که مبنا فقط شیوهی نوشتن است، نه تغییر مقدار. «سیزده» همان سیزده است، چه آن را 13 بنویسیم، چه 1101، چه D؛ حافظه در هر سه حالت همان الگوی بیتهای 00001101 را نگه میدارد.
یک مقدار، چهار نوشتار
همهی کارتهای زیر دقیقاً یک عدد را نشان میدهند.
1101 2دودوییBinary · مبنای ۲
15 8هشتهشتیOctal · مبنای ۸
13 10دهدهیDecimal · مبنای ۱۰
D 16شانزدهشانزدهیHexadecimal · مبنای ۱۶
00001101
الگوی بیتهایی که در حافظه مینشیند (۸ بیت = ۱ بایت)
| مبنا | ارقام مجاز | نوشتن در C | چاپ با printf | کاربرد متداول |
|---|---|---|---|---|
| ۲ (دودویی) | 0 و 1 | 0b1101 (C23 و افزونهی GCC/Clang) | %b در C23؛ پشتیبانی آن به نسخهی کتابخانهی C بستگی دارد | سختافزار، بیتها، bitmask |
| ۸ (هشتهشتی) | 0 تا 7 | 015 (پیشوند صفر) | %o | مجوزهای فایل در یونیکس |
| ۱۰ (دهدهی) | 0 تا 9 | 13 | %d | محاسبات و ارتباط روزمره با انسان |
| ۱۶ (هگز) | 0 تا 9 و A تا F | 0xD (پیشوند 0x) | %x یا %X | آدرس حافظه، رنگها، محتوای بایتها |
چرا دقیقاً هگز و اکتال؟¶
دلیل اصلی این است که ۱۶ و ۸ توانهای دقیق عدد ۲ هستند: 16 = 2⁴ و 8 = 2³. در نتیجه هر رقم هگز دقیقاً معادل ۴ بیت و هر رقم هشتهشتی دقیقاً معادل ۳ بیت است. این یعنی تبدیل به دودویی و برعکس، بدون هیچ محاسبهای و فقط با «گروهبندی» انجام میشود (در بخشهای بعد خواهید دید). دهدهی چنین خاصیتی ندارد، چون ۱۰ توانی از ۲ نیست.
هگز: یک بایت (۸ بیت) دقیقاً با دو رقم هگز نوشته میشود؛ مثلاً
11111111میشودFF. یک عدد ۳۲بیتی هم فقط ۸ رقم هگز میخواهد، در حالی که دودوییاش ۳۲ رقم است.هشتهشتی: در ماشینهای قدیمی که طول کلمهشان مضرب ۳ بود (مثل ۱۲، ۲۴ یا ۳۶ بیت) بسیار طبیعی بود. امروز بیشتر در مجوزهای فایل یونیکس و ساختار
0...در زبان C دیده میشود.
نکتهی مهم: نوشتهی «10» بدون دانستن مبنا معنی ندارد: 10 2 برابر ۲ است، 10 8 برابر ۸، 10 10 برابر ۱۰ و 10 16 برابر ۱۶. به همین دلیل زبان C با پیشوندهای 0b، 0 و 0x مبنا را مشخص میکند.
جدول ۰ تا ۱۵ و توانهای دو¶
همانطور که در دهدهی بعد از ۹ رقمها تمام میشوند و 10 (یک «دهتایی» و صفر «یکی») میآید، در هگز هم بعد از F رقمها تمام میشوند و 10 (که یعنی ۱۶) میآید. چون برای ۱۰ تا ۱۵ رقم تکنمادی نداریم، از حروف A تا F استفاده میشود.
| دهدهی | دودویی (۴ بیتی) | هشتهشتی | هگز |
|---|---|---|---|
0 | 0000 | 0 | 0 |
1 | 0001 | 1 | 1 |
2 | 0010 | 2 | 2 |
3 | 0011 | 3 | 3 |
4 | 0100 | 4 | 4 |
5 | 0101 | 5 | 5 |
6 | 0110 | 6 | 6 |
7 | 0111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 | 16 | E |
15 | 1111 | 17 | F |
نکتهی مهم: ستون «دودویی» را بهخاطر بسپارید یا هر وقت لازم شد از روی ارزش بیتها (8 4 2 1) بسازید. این جدول ۱۶ ردیفی کلید همهی تبدیلهای سریع هگز است. حروف هگز بزرگ و کوچک بودنشان فرقی ندارد: 0xff و 0xFF یک مقدارند.
توانهای دو که بهتر است از بر باشند¶
| n | 2ⁿ (دهدهی) | هگز | هشتهشتی |
|---|---|---|---|
0 | 1 | 1 | 1 |
1 | 2 | 2 | 2 |
2 | 4 | 4 | 4 |
3 | 8 | 8 | 10 |
4 | 16 | 10 | 20 |
5 | 32 | 20 | 40 |
6 | 64 | 40 | 100 |
7 | 128 | 80 | 200 |
8 | 256 | 100 | 400 |
9 | 512 | 200 | 1000 |
10 | 1024 | 400 | 2000 |
11 | 2048 | 800 | 4000 |
12 | 4096 | 1000 | 10000 |
13 | 8192 | 2000 | 20000 |
14 | 16384 | 4000 | 40000 |
15 | 32768 | 8000 | 100000 |
16 | 65536 | 10000 | 200000 |
چند عدد از این جدول در عمل بارها پیش میآید: 2⁸ = 256 (تعداد حالتهای یک بایت)، 2¹⁰ = 1024 (یک «کیلو» در دنیای حافظه) و 2¹⁶ = 65536 (تعداد حالتهای ۱۶ بیت). به همین دلیل بیشینهی یک بایت بدون علامت 255 = 0xFF و بیشینهی ۱۶ بیت بدون علامت 65535 = 0xFFFF است.
تبدیل هر مبنا به دهدهی (بسط مکانی)¶
همهی مبناها از یک قاعدهی واحد پیروی میکنند: نمایش مکانی (Positional Notation). هر رقم بسته به جایگاهش در یک توان از مبنا ضرب میشود و جمع این حاصلضربها مقدار عدد است. شمارش جایگاهها از سمت راست و از توان صفر شروع میشود.
value = dₖ·bᵏ + … + d₂·b² + d₁·b¹ + d₀·b⁰
در این رابطه b مبنا و d رقمهاست. در دهدهی این کار را بیآنکه فکر کنیم میکنیم: 352 = 3×100 + 5×10 + 2×1. حالا همین را برای مبناهای دیگر انجام میدهیم:
نکتهی مهم: قبل از ضرب، حروف هگز را به مقدارشان تبدیل کنید (A=10 تا F=15). خطای رایج این است که F را مثل یک رقم تکواحدی حساب کنند.
تبدیل دهدهی به مبنای دلخواه (تقسیمهای متوالی)¶
برای رفتن در جهت مخالف، عدد را پشتسرهم بر مبنای مقصد تقسیم میکنیم و هر بار باقیمانده را یادداشت میکنیم. باقیماندهی هر تقسیم، «پایینترین رقمِ» باقیماندهی عدد در آن مبناست؛ پس اولین باقیمانده کمارزشترین رقم است و ما باید باقیماندهها را از آخر به اول بخوانیم. تقسیمها تا وقتی ادامه پیدا میکنند که خارجقسمت به صفر برسد.
مثال ثابت: تبدیل ۱۳ به دودویی.
| تقسیم | خارجقسمت | باقیمانده |
|---|---|---|
13 ÷ 2 | 6 | 1 ← کمارزشترین رقم |
6 ÷ 2 | 3 | 0 |
3 ÷ 2 | 1 | 1 |
1 ÷ 2 | 0 | 1 ← پرارزشترین رقم |
خواندن باقیماندهها از پایین به بالا: 1101 2. همین روش برای هر مبنای دیگری هم کار میکند؛ مثلاً 156 ÷ 16 = 9 با باقیماندهی 12 که رقم هگز C است، و 9 ÷ 16 = 0 با باقیماندهی 9؛ پس 156 10 = 9C 16. به همین ترتیب 100 10 = 144 8.
انیمیشن تقسیمهای متوالی
یک عدد و یک مبنای مقصد انتخاب کنید و تقسیمها را یکییکی ببینید.
عدد دهدهی (۰ تا ۱٬۰۰۰٬۰۰۰) مبنای مقصددودویی (۲)هشتهشتی (۸)هگز (۱۶)
پخش دوباره
میانبر: دودویی ↔ هشتهشتی ↔ هگز¶
چون ۱۶ و ۸ توانهای ۲ هستند، برای تبدیل بین دودویی، هشتهشتی و هگز هیچ محاسبهای لازم نیست؛ فقط بیتها را گروهبندی میکنیم.
دودویی ← هگز: بیتها را از سمت راست چهارتاچهارتا جدا کنید (اگر گروه آخر کم داشت، از چپ صفر اضافه کنید)، سپس هر گروه را با جدول ۰ تا ۱۵ به یک رقم هگز تبدیل کنید.
دودویی ← هشتهشتی: همین کار، ولی گروههای سهتایی.
هگز یا هشتهشتی ← دودویی: هر رقم را با ۴ (یا ۳) بیت جایگزین کنید.
هگز ← هشتهشتی (و برعکس): از دودویی بهعنوان واسطه استفاده کنید.
مثال: 101011110011 2
1010
↓A
1111
↓F
0011
↓3
گروههای چهارتایی ← AF3 16
101
↓5
011
↓3
110
↓6
011
↓3
گروههای سهتایی ← 5363 8 (هر دو برابر ۲۸۰۳ دهدهی)
برعکسش هم ساده است: 3B7 16 را باز کنید: 3 → 0011، B → 1011، 7 → 0111؛ پس 001110110111 2.
آزمایشگاه بیتها
روی هر بیت کلیک کنید تا ۰ و ۱ شود، و همزمان مقدار آن در همهی مبناها و گروهبندیاش را ببینید. زیر هر بیت، ارزش آن نوشته شده است.
یا یک عدد دهدهی بنویسید (۰ تا ۶۵۵۳۵)
گروهبندی ۴تایی (هگز)
گروهبندی ۳تایی (هشتهشتی)
13
255
1024
2803 (AF3)
51966 (CAFE)
65535
دهدهی
دودویی
هشتهشتی (در C)
هگز (در C)
در حالت ۳تایی، چون ۱۶ بر ۳ بخشپذیر نیست، گروه اول با صفرهای اضافهی سمت چپ کامل شده است.
اعشار در مبناهای مختلف (برای کنجکاوها)¶
اعداد اعشاری هم در مبناهای دیگر قابل نوشتناند. بخش صحیح مثل قبل تبدیل میشود؛ برای بخش اعشاری بهجای تقسیم، پشتسرهم در مبنا ضرب میکنیم و هر بار بخش صحیح حاصل را یادداشت میکنیم (این بار از بالا به پایین خوانده میشود).
مثال: 0.625 در دودویی. 0.625×2 = 1.25 (رقم ۱)، 0.25×2 = 0.5 (رقم ۰)، 0.5×2 = 1.0 (رقم ۱ و پایان). نتیجه: 0.101 2، چون 1/2 + 0/4 + 1/8 = 0.625.
نکتهی مهم: فقط کسرهایی که مخرجشان (پس از سادهسازی) توانی از ۲ باشد، در دودویی پایانپذیرند. عدد 0.1 اینطور نیست و در دودویی بهصورت 0.000110011001100… تا بینهایت ادامه دارد. همین دلیل ریشهای خطای نمایش اعشاری در float و double است: حافظه ناچار است این رشتهی بیپایان را در تعداد محدودی بیت ببرد.
برای کنجکاوها: جزئیات دقیق ذخیرهی اعداد اعشاری در استاندارد IEEE 754 تعریف شده است و در درسهای بعدی (و در منابع انتهای فایل) میتوانید دنبالش کنید.
هگز و اکتال در دنیای واقعی¶
هگز و اکتال فقط تمرین مدرسهای نیستند. چند جای واقعی که حتماً با آنها روبهرو میشوید:
۱) رنگها در وب و طراحی¶
رنگ #RRGGBB سه بایت است: شدت قرمز، سبز و آبی، هر کدام با یک بایت (دو رقم هگز) و در بازهی ۰ تا ۲۵۵. بهعنوان نمونه، دو رنگ اصلی همین فایل را ببینید:
#233870
R = 0x23 = 35 · G = 0x38 = 56 · B = 0x70 = 112
#783C64
R = 0x78 = 120 · G = 0x3C = 60 · B = 0x64 = 100
۲) مجوزهای فایل در یونیکس (هشتهشتی)¶
هر فایل سه دسته مجوز دارد (مالک، گروه، بقیه) و هر دسته سه بیت: خواندن (r)، نوشتن (w)، اجرا (x). چون هر دسته سه بیت است، یک رقم هشتهشتی برایش کافی است؛ دستور chmod 755 file یعنی:
مالک
7
111
rwx
گروه
5
101
r-x
بقیه
5
101
r-x
در مجموع rwxr-xr-x؛ یعنی مالک همهکاره است و دیگران فقط میتوانند بخوانند و اجرا کنند.
۳) کاراکترها و کد ASCII¶
| کاراکتر | دهدهی | هگز | هشتهشتی |
|---|---|---|---|
'A' | 65 | 0x41 | 0101 |
'a' | 97 | 0x61 | 0141 |
'0' | 48 | 0x30 | 060 |
'\n' | 10 | 0x0A | 012 |
حروف بزرگ و کوچک انگلیسی در جدول ASCII دقیقاً 0x20 (یعنی ۳۲) با هم فاصله دارند؛ یعنی فقط یک بیت (بیت پنجم) تفاوتشان است. توضیح بیشتر در بخش char، ASCII و Unicode آمده است.
۴) آدرس حافظه، شبکه و ابزارهای اشکالزدایی¶
آدرسها در حافظه (مثل خروجی %p در printf یا ابزارهایی مثل GDB و Valgrind که بعداً میبینید)، آدرس MAC کارت شبکه (۶ بایت، مثل 00:1A:2B:3C:4D:5E) و آدرسهای IPv6 (۸ گروه ۱۶بیتی، هر گروه ۴ رقم هگز) همگی با هگز نوشته میشوند. دلیلش همان خاصیت «هر رقم = ۴ بیت» است که اندازهی نوشته را کوتاه و خواندنش را ممکن میکند.
۵) برای کنجکاوها: ترتیب بایتها در حافظه (Endianness)¶
وقتی عددی مثل 0x12345678 بیشتر از یک بایت جا میگیرد، سؤال این است که کدام بایت در کمترین آدرس بنشیند. روی بیشتر رایانههای امروزی (از جمله x86-64) روش Little-endian رایج است، یعنی کمارزشترین بایت اول میآید:
نوشتار معمول عدد
12پرارزشترین345678کمارزشترین
در حافظه (Little-endian)
78آدرس +056+134+212+3
لازم نیست حالا آن را حفظ کنید؛ فقط بدانید اگر روزی بایتهای یک عدد را در حافظه «برعکس» دیدید، خطا نیست، قاعده است.
نوشتن و چاپ مبناها در C¶
در C مبنای یک عدد ثابت (Literal) را پیشوند آن مشخص میکند. این قاعده در بخش «ثابتها» و در کتاب K&R هم آمده است؛ اما همینجا که در مورد مبناها حرف میزنیم، جمعبندیاش بهتر است:
بدون پیشوند ← دهدهی:
13پیشوند
0xیا0X← هگز:0xDپیشوند
0← هشتهشتی:015پیشوند
0b← دودویی (در C23 استاندارد شده و سالهاست در GCC و Clang هم بهصورت افزونه پشتیبانی میشود)
%%c
#include <stdio.h>
int main(void) {
int a = 13; // دهدهی
int b = 0xD; // هگز (پیشوند 0x)
int c = 015; // هشتهشتی (پیشوند صفر)
int d = 0b1101; // دودویی (C23 / افزونهی GCC و Clang)
printf("%d %d %d %d\n", a, b, c, d); // 13 13 13 13
return 0;
}هر چهار متغیر کاملاً یک مقدار دارند؛ پیشوند فقط به کامپایلر میگوید رقمها را چطور بخواند و روی نوع یا مقدار تأثیری ندارد.
چاپ یک عدد در مبناهای مختلف¶
برای چاپ، بهجای %d از %o، %x یا %X استفاده میکنیم. اگر پیشوند هم بخواهیم، پرچم # آن را اضافه میکند (جزئیات پرچمها در بخش قالببندی دقیقتر خروجی آمده است).
%%c
#include <stdio.h>
int main(void) {
int x = 255;
printf("%d\n", x); // 255 (دهدهی)
printf("%o\n", x); // 377 (هشتهشتی)
printf("%x\n", x); // ff (هگز، حروف کوچک)
printf("%X\n", x); // FF (هگز، حروف بزرگ)
printf("%#x %#o\n", x, x); // 0xff 0377 (با پیشوند)
printf("%04X\n", 13); // 000D (چهار رقم، با صفر پیشین)
return 0;
}نکتهی مهم: %x بهتنهایی پیشوند 0x را چاپ نمیکند؛ خروجی ff است نه 0xff. برای پیشوند از %#x یا 0x%x استفاده کنید.
دامهای رایج¶
%%c
printf("%d\n", 10); // 10
printf("%d\n", 010); // 8 ← صفر ابتدایی یعنی هشتهشتی!
printf("%d\n", 0x10); // 16
// int bad = 09; // خطای کامپایل: ۹ رقم هشتهشتی نیستهمین رفتار «صفر ابتدایی = هشتهشتی» دلیل میشود برنامهنویسها در C معمولاً عدد را با صفر پیشین نمینویسند (مثلاً 007 یا 08)، مگر واقعاً قصد هشتهشتی داشته باشند.
هگز و اکتال برای کاراکترها¶
%%c
char c1 = 65; // دهدهی
char c2 = 0x41; // هگز
char c3 = 0101; // هشتهشتی
char c4 = 'A'; // خود کاراکتر
printf("%c %c %c %c\n", c1, c2, c3, c4); // A A A Aخواندن هگز از ورودی¶
همانطور که %d برای خواندن دهدهی است، %x در scanf هگز میخواند و %o هشتهشتی. متغیر مقصد در این حالت بهتر است unsigned int باشد (مفهوم «بدون علامت» در بخش signed و unsigned آمده است).
%%c
unsigned int v;
scanf("%x", &v); // اگر کاربر بنویسد: ff
printf("%u\n", v); // 255برای کنجکاوها¶
چاپ دودویی بدون %b: اگر کامپایلر شما %b را پشتیبانی نکند، میتوان بیتها را با عملگرهای بیتی (>> و &) جدا کرد. لازم نیست این کد را همین الان کامل بفهمید؛ در بخش عملگرهای بیتی دلیل کارکردش روشن میشود:
%%c
#include <stdio.h>
int main(void) {
unsigned char n = 13;
printf("%d%d%d%d%d%d%d%d\n",
(n >> 7) & 1, (n >> 6) & 1, (n >> 5) & 1, (n >> 4) & 1,
(n >> 3) & 1, (n >> 2) & 1, (n >> 1) & 1, n & 1); // 00001101
return 0;
}عدد منفی در هگز: روی سیستمی که int آن ۳۲ بیت است، عدد -1 یعنی همهی ۳۲ بیت برابر ۱، و در هگز میشود ffffffff (مثلاً با printf("%x\n", (unsigned int)-1);). اینکه چرا منفیها اینطور ذخیره میشوند (مکمل دو) در مبحث بخش اعداد علامتدار و بدون علامت و درسهای بعدی بازتر میشود.
خطاهای رایج دربارهی مبناها¶
این جدول خطاهایی را جمع کرده که در کلاسهای مقدماتی بسیار دیده میشود:
| اشتباه رایج | توضیح و راهحل |
|---|---|
فکر کردن به اینکه 010 و 10 یکیاند | 010 در C هشتهشتی است و برابر ۸. برای دهدهی صفر ابتدایی نگذارید. |
نوشتن 08 یا 09 | ارقام ۸ و ۹ در هشتهشتی وجود ندارند و کامپایلر خطای «invalid digit in octal constant» میدهد. |
نوشتن حرف خارج از A تا F در هگز، مثل 0xFG | G رقم هگز نیست. کامپایلر آن را بهعنوان پسوند نامعتبر عدد میبیند و خطا میدهد. |
گمان اینکه 0x10 برابر ۱۰ است | 0x10 یعنی 1×16 + 0 = 16. پیشوند فقط مبنا را نشان میدهد و جزو مقدار نیست. |
انتظار پیشوند 0x از %x | %x فقط رقمها را چاپ میکند. برای پیشوند از %#x استفاده کنید. |
فکر کردن به اینکه 0xFF و 255 دو چیز متفاوت در حافظهاند | هر دو یک int با مقدار ۲۵۵ هستند؛ حافظه به شیوهی نوشتن شما کاری ندارد. |
| تبدیل گروههای دودویی بدون صفر پیشین | هر رقم هگز دقیقاً ۴ بیت است. مثلاً 1 باید 0001 نوشته شود، نه 1، وگرنه گروهبندی بههم میریزد. |
خواندن عدد هگز با %d | scanf("%d") ورودی ff را عدد نمیداند. برای هگز از %x استفاده کنید. |
ریختن عددی مثل 0x100 در unsigned char | بیشینهی یک بایت بدون علامت ۲۵۵ (یعنی 0xFF) است و 0x100 (۲۵۶) سرریز میکند. |
چالشهای کوتاه با پاسخ تاشو¶
این چالشهای کوتاه را قبل از باز کردن پاسخ، روی کاغذ حل کنید. هیچکدام به دستور شرطی یا حلقه نیاز ندارند.
چالش ۱ — دودویی به دهدهی: مقدار 101101 2 چند است؟
1×32 + 0×16 + 1×8 + 1×4 + 0×2 + 1×1 = 45
چالش ۲ — دهدهی به هگز و دودویی: عدد ۲۰۰ را به هگز و دودویی ببرید.
200 ÷ 16 = 12 با باقیماندهی 8؛ سپس 12 ÷ 16 = 0 با باقیماندهی 12 که C است. پس C8 16. با جدول ۰ تا ۱۵: C = 1100 و 8 = 1000، پس 11001000 2.
چالش ۳ — هگز به دودویی و دهدهی: مقدار 0x1F چیست؟
1 → 0001 و F → 1111؛ پس 00011111. در دهدهی: 1×16 + 15 = 31.
چالش ۴ — میانبر گروهبندی: 101011110011 2 را مستقیم به هگز و هشتهشتی ببرید.
چهارتایی: 1010 | 1111 | 0011 = AF3. سهتایی: 101 | 011 | 110 | 011 = 5363. پس AF3 16 و 5363 8.
چالش ۵ — بدون اجرا پیشبینی کنید: printf("%d %d %d\n", 10, 010, 0x10); چه چاپ میکند؟
10 8 16. عدد اول دهدهی است، دومی هشتهشتی (۸) و سومی هگز (۱۶).
چالش ۶ — خطایابی: کدام خطها خطای کامپایل میدهند؟ int a = 0xFG; و int b = 09; و int c = 0x1F;
دو خط اول خطا میدهند. در 0xFG حرف G رقم هگز نیست و در 09 رقم ۹ در هشتهشتی وجود ندارد. خط سوم درست است و برابر ۳۱.
چالش ۷ — چند رقم هگز لازم است تا همهی عددهای ۱۶ بیتی را بنویسیم؟ بزرگترینشان چیست؟
هر رقم هگز ۴ بیت است، پس ۱۶ بیت یعنی ۴ رقم هگز. بزرگترین مقدار بدون علامت 0xFFFF = 65535 است.
چالش ۸ — دهدهی ۴۸۸۷۹ را به هگز ببرید و حدس بزنید چرا معروف است.
48879 ÷ 16 = 3054 باقیمانده 15 (F)؛ 3054 ÷ 16 = 190 باقیمانده 14 (E)؛ 190 ÷ 16 = 11 باقیمانده 14 (E)؛ 11 ÷ 16 = 0 باقیمانده 11 (B). از پایین به بالا: BEEF 16. این کلمهی هگزی که با حروف A تا F ساخته میشود، در دنیای برنامهنویسی برای نشانهگذاری و شوخی بسیار به کار رفته است.
جدول مرجع سریع و منابع این بخش¶
| اگر میخواهید… | کار کنید |
|---|---|
| از مبنای b به دهدهی بروید | هر رقم را در توان مناسب مبنا (از راست و از توان صفر) ضرب و جمع کنید. |
| از دهدهی به مبنای b بروید | عدد را پشتسرهم بر b تقسیم کنید و باقیماندهها را از آخر به اول بخوانید. |
| دودویی را به هگز ببرید | از راست ۴تا۴تا گروه کنید و با جدول ۰ تا ۱۵ هر گروه را رقم کنید. |
| دودویی را به هشتهشتی ببرید | از راست ۳تا۳تا گروه کنید. |
| مبنا را در C مشخص کنید | 0b دودویی، 0 هشتهشتی، 0x هگز، بدون پیشوند دهدهی. |
| در printf چاپ کنید | %d دهدهی، %o هشتهشتی، %x/%X هگز؛ با پرچم # پیشوند هم میآید. |
برای مطالعهی بیشتر دربارهی نمایش اعداد و مبناها:
Randal E. Bryant & David R. O’Hallaron, Computer Systems: A Programmer’s Perspective (CS:APP)، فصل ۲، بخش «Information Storage» که نماد هگز را بهروشنی و با تمرین معرفی میکند.
Brian W. Kernighan & Dennis M. Ritchie, The C Programming Language، بخش «Constants» برای قواعد ثابتهای هشتهشتی و هگز.
CS50x، هفتهی ۰ (مبنای دو و نمایش اعداد) و هفتهی ۴ (حافظه و هگز).
Donald E. Knuth, The Art of Computer Programming، جلد ۲، بخش «Positional Number Systems» برای بحث نظری و کامل مبناها.
%%c
printf("%zu\n", sizeof(int)); // معمولاً چاپ میکند: 4تفاوت float و double****: هر دو برای اعداد اعشاری هستند، اما double دقت بیشتری دارد (تعداد ارقام اعشار بیشتر) و در اکثر پروژههای واقعی ترجیح داده میشود، مگر جایی که حافظه بسیار محدود باشد.
long و long long — وقتی int کافی نیست¶
همانطور که در بخش «حوزهی مقادیر و سرریز» خواهیم دید، int معمولاً فقط تا حدود ۲.۱ میلیارد را پوشش میدهد. اگر بخواهیم عددی بزرگتر از این (مثلاً جمعیت جهان، یا نتیجهی ضرب چند عدد بزرگ) را نگه داریم، باید از long یا long long استفاده کنیم:
%%c
#include <stdio.h>
int main() {
long long population = 8000000000LL; // برای قابلحمل بودن روی سیستمهایی که long فقط ۳۲ بیت است
long long distance = 9460730472580800LL; // یک سال نوری بر حسب متر؛ پسوند LL یعنی «long long»
printf("Population: %lld\n", population);
printf("Distance (light-year): %lld\n", distance);
return 0;
}نکات کلیدی:
برای چاپ
longاز%ldو برایlong longاز%lldاستفاده کنید (نه%d، چون%dمخصوصintمعمولی است و خروجی اشتباه میدهد).پسوند
LیاLLدر انتهای عدد ثابت (مثل100000L) به کامپایلر میگوید که این عدد را از همان ابتدا با نوعlong/long longدر نظر بگیرد، نهint— این کار از overflow زودهنگام در محاسبات میانی جلوگیری میکند.اندازهی
longبه پیادهسازی وابسته است. استاندارد C برایlong longدستکم بازهای معادل یک عدد صحیح علامتدار ۶۴ بیتی را تضمین میکند، اما بهتر است بهجای فرضکردن تعداد بایتها، در صورت نیازsizeofو حدود تعریفشده در هدرها را بررسی کنیم. برای مقادیری که از بازهی معمولintبزرگترند،long longاغلب انتخاب قابلحملتری است.
اعداد علامتدار و بدون علامت (signed / unsigned)¶
نوعهای صحیح در C میتوانند علامتدار یا بدون علامت باشند:
%%c
signed int temperature = -5;
unsigned int count = 42U;unsigned نمیتواند مقدار منفی را نمایش دهد و در عوض بخش بیشتری از بیتها را برای مقادیر غیرمنفی استفاده میکند. نکتهی مهم این است که ترکیب signed و unsigned در یک عبارت میتواند نتیجههای غافلگیرکننده ایجاد کند؛ پس در کد مقدماتی بهتر است بیدلیل از unsigned استفاده نکنیم.
برای کنجکاوها: در
<stdint.h>نوعهایی مانندint32_tوuint64_tوجود دارند که وقتی دقیقاً به تعداد مشخصی بیت نیاز داریم مفیدند. در این درس دانستن نام آنها کافی است؛ جزئیاتشان در برنامهنویسی سیستمی اهمیت بیشتری پیدا میکند.
دقت اعشاری و خطای نمایش¶
float و double همهی اعداد اعشاری را دقیق نگه نمیدارند. مثلاً مقدار 0.1 در نمایش دودویی متناهی نیست و معمولاً به نزدیکترین مقدار قابلنمایش گرد میشود:
%%c
#include <stdio.h>
int main(void) {
double x = 0.1 + 0.2;
printf("%.17f\n", x);
return 0;
}ممکن است خروجی چیزی نزدیک به 0.30000000000000004 باشد. نتیجهی آموزشی مهم: برای مقایسهی اعداد اعشاری، همیشه x == 0.3 بهترین انتخاب نیست.
پنجرهی بیشتر: استاندارد رایج نمایش اعداد اعشاری در سختافزار IEEE 754 نام دارد. فعلاً فقط اسم آن را بدانید؛ در درس معماری کامپیوتر یا محاسبات عددی میتوان عمیقتر به آن برگشت.
اندازهی نوعها: «معمولاً» با «تضمینشده» فرق دارد¶
استاندارد C حداقلهایی را تضمین میکند، اما الزام نمیکند که مثلاً int همیشه دقیقاً ۴ بایت باشد. برای کد قابلحمل:
%%c
#include <stdio.h>
printf("int: %zu bytes\n", sizeof(int));
printf("double: %zu bytes\n", sizeof(double));عملگر sizeof خروجیای از نوع size_t میدهد و برای چاپ آن از %zu استفاده میکنیم.
۲. قواعد نامگذاری متغیرها¶
نام متغیر نمیتواند دلخواه باشد؛ باید از قواعد زیر پیروی کند:
فقط میتواند شامل حروف، اعداد و آندرلاین (
_) باشد.نمیتواند با عدد شروع شود (
2valueغلط است،value2درست است).به بزرگی و کوچکی حروف حساس است (
Ageوageدو متغیر متفاوتاند).نمیتواند از کلمات کلیدی زبان (مثل
int,for,return) استفاده کند.بهتر است نامی معنادار و خواناکه انتخاب شود (
studentCountبهتر ازxاست).
int studentCount = 30; // خوب
int 2ndYear = 5; // خطای کامپایل (شروع با عدد)
int student count = 10; // خطای کامپایل (فاصله مجاز نیست)(نمایشی — این نمونه عمداً اجرا نمیشود)
سبکهای رایج نامگذاری (Naming Convention): قواعد بالا فقط میگویند چه نامی «مجاز» است؛ اما برنامهنویسها برای نامهای چندکلمهای (مثل «تعداد دانشجو») روی چند سبک قرارداد کردهاند. خود C سبک خاصی را اجباری نکرده است.
| سبک | مثال | منشأ و جاهایی که استفاده میشود |
|---|---|---|
camelCase | studentCount | ریشه در جامعهی زبان Smalltalk (دههی ۱۹۷۰)؛ امروز برای متغیر و تابع در Java و JavaScript رایج است. |
PascalCase | StudentCount | بهنام زبان Pascal (نیکلاوس ویرت، ۱۹۷۰)؛ برای نام کلاس و نوع در Java و C#، و در Windows API. |
snake_case | student_count | سنتی در Unix و C؛ کتابخانهی استاندارد C (مثل size_t و strlen)، هستهی لینوکس، Python (استاندارد PEP 8) و Rust. |
UPPER_SNAKE_CASE | MAX_STUDENTS | مخصوص ثابتها و ماکروها در C، مثل INT_MAX در <limits.h>. |
| نت مجارستانی (Hungarian) | iCount ، szName | ابداع چارلز سیمونی (Charles Simonyi)، برنامهنویس Xerox PARC و بعد Microsoft؛ در Windows API (مثل hWnd) دیده میشود، اما امروز کمتر توصیه میشود. |
kebab-case | student-count | در C مجاز نیست (- عملگر منفی است)؛ در CSS و آدرس وبسایتها استفاده میشود. |
%%c
int student_count = 30; // snake_case
int studentCount = 30; // camelCase
#define MAX_STUDENTS 100 // UPPER_SNAKE_CASE (ثابت/ماکرو)این سبکها «قانون زبان» نیستند، بلکه قرارداد تیمها و راهنماهای سبک کدنویسیاند (مثل Linux kernel coding style، PEP 8 در Python و راهنمای کدنویسی Google). در درس، هر سبکی را انتخاب کردید، در کل برنامه همان را ادامه دهید.
چند ظرافت نامگذاری که ارزش دانستن دارند¶
نامهایی که با دو آندرلاین (
__name) شروع میشوند یا الگوهای خاصی از آندرلاین و حرف بزرگ دارند، برای پیادهسازی زبان/کتابخانه رزرو شدهاند؛ برای کد دانشجویی از آنها دوری کنید.نام متغیر معنادار باشد، اما لازم نیست تبدیل به یک جملهی طولانی شود.
سبکهایی مثل
camelCaseوsnake_caseهر دو رایجاند؛ مهمتر از انتخاب یکی، ثبات در کل پروژه است.مفهوم Scope در فصل توابع کاملتر بررسی میشود؛ فعلاً بدانید دو متغیر همنام در محدودههای متفاوت الزاماً یک متغیر نیستند.
۳. حوزهی مقادیر و سرریز (Overflow)¶
هر نوع داده، بهخاطر تعداد بیتهای محدودی که در حافظه اشغال میکند، فقط میتواند بازهی مشخصی از اعداد را نگه دارد. برای مثال int معمولاً بین تقریباً -۲٬۱۴۷٬۴۸۳٬۶۴۸ تا ۲٬۱۴۷٬۴۸۳٬۶۴۷ را پوشش میدهد.
وقتی نتیجهی یک محاسبه از بازهی نوع داده خارج شود، با سرریز (Overflow) روبهرو میشویم. نکتهی علمی مهم این است که در C، رفتار سرریز عدد صحیح علامتدار (signed int) طبق استاندارد «تعریفنشده» (Undefined Behavior) است؛ بنابراین نباید روی برگشتن خودکار عدد از انتهای بازه به ابتدای آن حساب کنیم. در بسیاری از ماشینهای امروزی ممکن است ظاهراً چنین رفتاری دیده شود، اما برنامهی قابلاعتماد نباید به آن وابسته باشد. در مقابل، سرریز انواع unsigned طبق حساب پیمانهای تعریف شده است.
%%c
#include <limits.h>
int x = INT_MAX; // بزرگترین مقدار ممکن برای int
printf("%d\n", x + 1); // این عبارت برای signed int وارد محدودهی Undefined Behavior میشوداین یکی از رایجترین منابع باگ در برنامههای واقعی است — همیشه به بازهی نوع دادهای که استفاده میکنید توجه کنید.
چطور بازهی واقعی نوعها را از خود C بپرسیم؟¶
بهجای حفظکردن عددها، میتوان از هدر <limits.h> استفاده کرد:
%%c
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("INT_MIN = %d\n", INT_MIN);
printf("INT_MAX = %d\n", INT_MAX);
printf("UINT_MAX = %u\n", UINT_MAX);
return 0;
}برای انواع اعشاری نیز <float.h> ثابتهایی دربارهی دقت و محدوده ارائه میکند.
چهار واژهی خطا که از همین حالا باید بشناسیم¶
| نوع مشکل | نمونه | معمولاً چه زمانی دیده میشود؟ |
|---|---|---|
| Syntax Error |
| زمان کامپایل |
| Warning |
| زمان کامپایل، ولی ممکن است فایل اجرایی ساخته شود |
| Runtime Error |
| هنگام اجرا |
| Logic Error |
| برنامه اجرا میشود، خروجی غلط است |
مفهوم مهمتر: Undefined Behavior. بعضی عملیات در C آنقدر خطرناکاند که استاندارد نتیجهی مشخصی برایشان تعریف نمیکند؛ مثل سرریز
signed intیا دسترسی خارج از محدودهی آرایه. این مفهوم در ادامهی درس بارها برمیگردد.
۴. ثابتها (Constants)¶
گاهی میخواهیم مقداری در طول برنامه هرگز تغییر نکند. برای این کار دو روش رایج داریم:
روش اول: کلمهی کلیدی const
%%c
const float PI = 3.14159;
// PI = 3.0; // خطای کامپایل: نمیتوان ثابت را تغییر دادروش دوم: دستور پیشپردازنده #define
%%c
#define PI 3.14159تفاوت اصلی: const یک متغیر واقعی با نوع مشخص است که کامپایلر آن را چک میکند؛ #define صرفاً یک جایگزینی متنی قبل از کامپایل است و نوع ندارد. در پروژههای مدرن، استفاده از const معمولاً توصیه میشود.
نکتهی دقیق:
constدر C به این معناست که از طریق آن نام اجازهی تغییر مقدار نداریم؛ این مفهوم با «ثابت زمان کامپایل» در همهی موقعیتها یکی نیست. از طرف دیگر،#defineاصلاً متغیر ایجاد نمیکند و مرحلهی پیشپردازش آن را بهصورت متنی جایگزین میکند. ماکروها قابلیتهای بیشتری هم دارند، اما استفادهی بیاحتیاط از آنها میتواند خطاهای ظریفی بسازد.
Literalها و پسوندها¶
خودِ عددهایی که مستقیماً در کد مینویسیم literal نام دارند. پسوندها به کامپایلر در تعیین نوع آنها کمک میکنند:
42 // معمولاً int
42U // unsigned int
42L // long
42LL // long long
3.14 // double
3.14f // float(نمایشی — این نمونه عمداً اجرا نمیشود)
این موضوع زمانی مهم میشود که محاسبه قبل از ذخیرهشدن در متغیر سرریز کند.
۵. تبدیل نوع (Type Casting)¶
گاهی لازم است مقدار یک نوع داده را به نوع دیگری تبدیل کنیم.
تبدیل ضمنی (Implicit Casting): کامپایلر خودش، بدون اینکه از او بخواهیم، تبدیل را انجام میدهد.
%%c
int a = 5;
double b = a; // int بهطور خودکار به double تبدیل میشودتبدیل صریح (Explicit Casting): خودمان بهصراحت نوع را مشخص میکنیم.
%%c
double result = 7 / 2; // نتیجه: 3.0 (چون هر دو عدد int هستند و تقسیم صحیح انجام میشود)
double correct = (double)7 / 2; // نتیجه: 3.5 (چون یکی از اعداد به double تبدیل شده)نکتهی رایج برای مبتدیان: تقسیم دو عدد
intهمیشه نتیجهیintمیدهد (بخش اعشاری قطع میشود)، حتی اگر نتیجه را در یک متغیرdoubleبریزید. برای گرفتن نتیجهی اعشاری، حداقل یکی از دو عدد بایدcastشود.
نکتهی کوچک — نمایش عدد در مبنای دیگر با printf: همان عددی که در حافظه ذخیره شده را میتوانید مستقیماً بهصورت هگزادسیمال یا اکتال هم چاپ کنید، بدون هیچ تبدیل دستی:
%%c
int x = 255;
printf("%d\n", x); // 255 (دهدهی)
printf("%x\n", x); // ff (هگزادسیمال)
printf("%o\n", x); // 377 (اکتال)این ارتباط مستقیمی با مبحث سیستمهای عددی دارد که پیشتر خواندهاید.
تبدیل نوع، promotion و از دست رفتن اطلاعات¶
تبدیل نوع همیشه بیخطر نیست:
%%c
double price = 19.99;
int whole = (int)price; // 19؛ بخش اعشاری حذف میشود، گرد نمیشودهمچنین انواع کوچکتر مثل char و short در بسیاری از عبارتهای محاسباتی ابتدا به int ارتقا پیدا میکنند؛ به این فرایند integer promotion میگویند.
پنجرهی بیشتر: مجموعه قوانین تبدیل ضمنی در C با نام usual arithmetic conversions شناخته میشود. حفظ کردن جزئیات آن در این مرحله لازم نیست، اما وقتی ترکیبی از
int،unsigned،floatوdoubleدر یک عبارت دیدید، بدانید پشت صحنه قواعد مشخصی برای تبدیل وجود دارد.
تمرین خطایابی کوتاه: خروجی را قبل از اجرا پیشبینی کنید¶
%%c
int a = 7;
int b = 2;
double x = a / b;
double y = (double)a / b;
printf("%.1f %.1f\n", x, y);خروجی
xچیست؟خروجی
yچیست؟تبدیل نوع در کدام مرحله باید رخ دهد تا بخش اعشاری از بین نرود؟
جمعبندی و تمرینهای این بخش¶
انواع داده:
int,float,double,char,boolقواعد نامگذاری معتبر
بازهی مقادیر و خطر Overflow
ثابتها:
constدر برابر#defineتبدیل نوع: implicit در برابر explicit
تمرین ۱ — محاسبهی سن¶
برنامهای بنویسید که سن کاربر را در یک int بگیرد، آن را در ۲ (بهعنوان double) ضرب کند و با تبدیل نوع صریح چاپ کند.
تمرین ۲ — رشد باکتری و کشف Overflow¶
فرض کنید یک جمعیت باکتری از 1 شروع میشود و در هر مرحله دو برابر میشود.
برنامهای بنویسید که یک متغیر از نوع int را از 1 شروع کند و در هر مرحله مقدار آن را در 2 ضرب کند. بعد از هر مرحله مقدار را چاپ کنید و ببینید با زیاد شدن مقدار، چه اتفاقی برای عدد میافتد.
هدف تمرین: میخواهیم Overflow را فقط در تئوری نبینید؛ خودتان رشد سریع عدد را اجرا کنید و ببینید وقتی مقدار از ظرفیت نوع داده عبور کند چه مشکلی به وجود میآید.
راهنمایی: فعلاً نیازی به حلقه ندارید. میتوانید چند بار پشت سر هم بنویسید:
> x *= 2; > printf("%d\n", x); >و مرحلهبهمرحله خروجی را بررسی کنید.
نکته: رفتار Overflow برای
intعلامتدار در استاندارد C تضمینشده نیست؛ هدف این تمرین مشاهدهی مفهوم سرریز در عمل است. برای آزمایش کاملاً قابلپیشبینی، بعداً میتوانید همین ایده را با انواع unsigned بررسی کنید.
تمرین ۳ — مبدل فارنهایت به سلسیوس¶
برنامهای بنویسید که یک دما بر حسب فارنهایت بگیرد و آن را به سلسیوس تبدیل کند (C = (F - 32) * 5 / 9).
این یکی از قدیمیترین و معروفترین تمرینهای آموزش C است؛ نسخهی اصلی آن دقیقاً همین برنامه است که در کتاب کلاسیک The C Programming Language نوشتهی Brian Kernighan و Dennis Ritchie (معروف به کتاب K&R) بهعنوان یکی از اولین برنامههای آموزشی کتاب معرفی شده است.
تمرین ۴ — محاسبهگر BMI¶
برنامهای بنویسید که قد (بر حسب متر) و وزن (بر حسب کیلوگرم) را بگیرد و شاخص تودهی بدنی را حساب کند (BMI = weight / (height * height)).
این تمرین یک نمونهی کلاسیک برای تمرین متغیرهای اعشاری و ترتیب محاسبه است.
تمرین ۵ — شکار خطا: نوع دادهی نامناسب¶
کد زیر را بررسی کنید و بدون اجرا بگویید چه اشکالاتی دارد. سپس آن را اصلاح کنید:
%%c
int average = 17.8;
char grade = "A";
float pi = 3.141592653589793;
printf("%d %c %f\n", average, grade, pi);هدف، تشخیص تفاوت کاراکتر و رشته، تبدیل ضمنی و محدودیت دقت float است.
تمرین ۶ — مقایسهی float و double¶
عدد 1.0 / 3.0 را یکبار در float و یکبار در double ذخیره کنید و هر دو را با تعداد زیادی رقم اعشار چاپ کنید. تفاوت را توضیح دهید.
تمرین ۷ — بازهی نوعها با <limits.h>¶
برنامهای بنویسید که CHAR_BIT، INT_MIN، INT_MAX و UINT_MAX را چاپ کند. سپس حدس بزنید سیستم شما برای int چند بیت استفاده میکند.
فصل ۲: ورودی/خروجی و عملگرهای پایه¶
۱. ورودی و خروجی: printf و scanf¶
printf — چاپ خروجی¶
printf("Age: %d\n", age);(نمایشی — این نمونه عمداً اجرا نمیشود)
printf از Format Specifierها استفاده میکند تا بداند هر متغیر را با چه فرمتی چاپ کند:
| Specifier | نوع داده |
|---|---|
%d | int |
%f | float |
%lf | double (در scanf؛ در printf هر دو %f هستند) |
%c | char |
%s | رشته (string / آرایهی کاراکتر) |
قالببندی دقیقتر خروجی¶
printf فقط برای چاپ ساده نیست. میتوان عرض، تعداد رقم اعشار و تراز را هم کنترل کرد:
%%c
double gpa = 17.4567;
printf("%.2f\n", gpa); // 17.46
printf("%8.2f\n", gpa); // حداقل عرض 8 کاراکترچند escape sequence پرکاربرد:
| دنباله | معنی |
|---|---|
\n | رفتن به خط بعد |
\t | Tab |
\" | چاپ " داخل رشته |
\\ | چاپ backslash |
نکته: در
printfبرایdoubleاز%fاستفاده میشود؛ اما درscanf،%fبرایfloat*و%lfبرایdouble*است. این تفاوت از رایجترین خطاهای مبتدیان است.
scanf — گرفتن ورودی از کاربر¶
%%c
int age;
scanf("%d", &age);نکتهی حیاتی: برای متغیرهای عددی و کاراکتری، باید از علامت & (آدرس متغیر) قبل از نام متغیر استفاده کنید — چون scanf نیاز دارد بداند مقدار را کجا در حافظه بنویسد.
%%c
int age;
float gpa;
char grade;
printf("Enter age, GPA, grade: ");
scanf("%d %f %c", &age, &gpa, &grade);برای رشتهها (
%s) از&استفاده نمیشود، چون نام آرایه بهخودیخود آدرس است — این نکته را در جلسات مربوط به آرایهها و رشتهها بیشتر توضیح میدهیم.
مقدار بازگشتی scanf را نادیده نگیریم¶
scanf تعداد ورودیهایی را که با موفقیت خوانده و تبدیل کرده برمیگرداند:
%%c
int age;
int result = scanf("%d", &age);
printf("items read: %d\n", result);اگر کاربر بهجای عدد، متن وارد کند، result میتواند 0 شود. در برنامههای واقعی باید این حالت را مدیریت کنیم؛ بعد از یادگیری شرطها میتوانیم ورودی نامعتبر را بهتر کنترل کنیم.
فاصلهها در format string¶
در scanf، وجود فاصله قبل از %c معمولاً عمدی است:
scanf(" %c", &grade);(نمایشی — این نمونه عمداً اجرا نمیشود)
این فاصله باعث میشود whitespace باقیمانده (مثلاً Enter قبلی) رد شود. بدون آن ممکن است %c همان \n باقیمانده را بخواند.
دربارهی %s: فقط تا اولین فاصله¶
scanf("%s", name) برای یک کلمه مناسب است، نه نام کامل چندکلمهای. ضمن آنکه باید مراقب ظرفیت آرایه بود. شکل محدودشده امنتر است:
%%c
char name[20];
scanf("%19s", name);پنجرهی بیشتر: برای خواندن خط کامل، تابع
fgetsمعمولاً انتخاب بهتری است و در مبحث رشتهها دوباره به آن برمیگردیم.
مثال کامل: چرا نام آرایهی رشته نیاز به & ندارد¶
برای اینکه این نکته کاملاً ملموس شود، بهتر است هم رشته و هم یک کاراکتر تکی را در یک برنامه با هم مقایسه کنیم و آدرس هرکدام را هم چاپ کنیم:
%%c
#include <stdio.h>
int main() {
char name[50];
char first_letter;
printf("Enter your full first name: ");
// ۱. آرایه name خودش آدرس خانه اول است؛ پس & نمیخواهد.
scanf("%s", name);
printf("Enter your favorite letter: ");
// ۲. متغیر عادی کاراکتری است؛ پس حتماً نیاز به آدرس (&) دارد.
scanf(" %c", &first_letter);
printf("\n--- Result ---\n");
printf("Name: %s\n", name);
printf("Address of name (name): %p\n", (void*)name);
printf("Address of name (&name[0]): %p\n", (void*)&name[0]);
printf("Favorite letter: %c (Address: %p)\n", first_letter, (void*)&first_letter);
return 0;
}نمونه خروجی ترمینال (Terminal Output):
Enter your full first name: Banafsheh
Enter your favorite letter: A
--- Result ---
Name: Banafsheh
Address of name (name): 0x7ff7bfe2f820
Address of name (&name[0]): 0x7ff7bfe2f820
Favorite letter: A (Address: 0x7ff7bfe2f853)نکتهی کلیدی از روی همین خروجی: مقدار آدرسی که با name و &name[0] چاپ میشود یکسان است. بیان دقیقتر این است که نام آرایه در بیشتر عبارتها به اشارهگری به عنصر اول آرایه تبدیل میشود (array-to-pointer decay). به همین دلیل scanf("%s", name) به اشارهگر خانهی اول دسترسی دارد و نیازی به &name نیست. توجه کنید name و &name از نظر نوع یکسان نیستند، هرچند ممکن است هنگام چاپ آدرس مقدار عددی یکسانی نشان دهند. در مقابل، first_letter یک متغیر معمولی است و برای نوشتن در آن باید &first_letter را به scanf بدهیم.
۲. عملگرهای محاسباتی، رابطهای و منطقی¶
عملگرهای محاسباتی (Arithmetic)¶
| عملگر | معنی | مثال |
|---|---|---|
+ | جمع | 5 + 2 → 7 |
- | تفریق | 5 - 2 → 3 |
* | ضرب | 5 * 2 → 10 |
/ | تقسیم | 5 / 2 → 2 (تقسیم صحیح!) |
% | باقیمانده (Modulo) | 5 % 2 → 1 |
کاربرد جالب: رمزنگاری سزار (Caesar Cipher)¶
یکی از قدیمیترین روشهای رمزنگاری در تاریخ (که به ژولیوس سزار نسبت داده میشود) این است: هر حرف پیام را چند جایگاه در الفبا جلو ببریم. چون هر char در واقع یک عدد (کد ASCII) است، این کار فقط با جمع عددی انجام میشود:
%%c
#include <stdio.h>
int main() {
char letter = 'A';
int shift = 3;
char encrypted = letter + shift; // 'A' (65) + 3 = 'D' (68)
printf("Encrypted: %c\n", encrypted); // چاپ میکند: D
return 0;
}برای رمزگشایی، کافی است همین مقدار shift را از حرف رمزشده کم کنیم. نکتهی مهم: این نسخهی ساده فقط برای یک حرف تکی و بدون عبور از انتهای الفبا (Z به A) کار میکند؛ نسخهی کاملتر که همهی این حالتها را هم پوشش بدهد، بعد از یادگیری if و حلقهها قابل تکمیل است.
عملگرهای رابطهای (Relational)¶
نتیجهی این عملگرها همیشه 0 (غلط) یا 1 (درست) است:
| عملگر | معنی |
|---|---|
== | برابر است با |
!= | برابر نیست با |
< | کوچکتر |
> | بزرگتر |
<= | کوچکتر یا مساوی |
>= | بزرگتر یا مساوی |
خطای رایج: استفاده از
=بهجای==برای مقایسه.=عملگر انتساب است،==عملگر مقایسه!
عملگرهای منطقی (Logical)¶
برای ترکیب چند شرط با هم استفاده میشوند:
| عملگر | معنی | مثال |
|---|---|---|
&& | و (AND) — هر دو باید درست باشند | (age > 18) && (hasID) |
| ` | ` | |
! | نقیض (NOT) | !isValid |
افزایش و کاهش: ++ و --¶
%%c
int x = 5;
x++; // x میشود 6
--x; // x دوباره میشود 5تفاوت x++ و ++x زمانی مهم میشود که داخل یک عبارت بزرگتر استفاده شوند:
%%c
int x = 5;
int a = x++; // a=5 سپس x=6
int b = ++x; // ابتدا x=7 سپس b=7برای خوانایی، در کدهای مقدماتی بهتر است افزایش/کاهش را تا حد امکان در خط جدا بنویسیم.
ارزیابی کوتاهمدار (Short-circuit)¶
در عملگرهای منطقی، C همیشه لازم نیست هر دو سمت را ارزیابی کند:
(a != 0) && (10 / a > 2)(نمایشی — این نمونه عمداً اجرا نمیشود)
اگر a != 0 غلط باشد، بخش دوم اجرا نمیشود. این رفتار short-circuit evaluation نام دارد و بعداً برای نوشتن شرطهای امن بسیار مفید است.
۳. عملگرهای انتسابی¶
علاوه بر = ساده، C راههای کوتاهتری برای «مقداردهی همراه با عملیات» دارد:
| عملگر | معادل | مثال |
|---|---|---|
+= | x = x + y | x += 5; |
-= | x = x - y | x -= 5; |
*= | x = x * y | x *= 5; |
/= | x = x / y | x /= 5; |
%= | x = x % y | x %= 5; |
%%c
int score = 10;
score += 5; // score اکنون برابر است با 15
score *= 2; // score اکنون برابر است با 30۴. عملگرهای بیتی (Bitwise Operators)¶
عملگرهای بیتی مستقیماً روی بیتهای نمایش دودویی اعداد صحیح کار میکنند. این مبحث ممکن است در شروع کمی انتزاعی باشد، اما پلی مستقیم بین برنامهنویسی و معماری کامپیوتر است.
| عملگر | نام | ایدهی ساده |
|---|---|---|
& | AND بیتی | فقط بیتهایی که در هر دو عدد ۱ هستند، ۱ میمانند |
| ` | ` | OR بیتی |
^ | XOR بیتی | اگر دو بیت متفاوت باشند، خروجی ۱ است |
~ | NOT بیتی | هر بیت را معکوس میکند |
<< | شیفت چپ | بیتها را به چپ میبرد |
>> | شیفت راست | بیتها را به راست میبرد |
عمل روی بیتها؛ اول با چشم ببینیم¶
در مثالهای زیر فقط ۴ بیت را برای سادهفهم شدن نشان میدهیم. در C، نوع واقعی عدد میتواند ۸، ۱۶، ۳۲ یا بیتهای بیشتری داشته باشد.
AND: &
0101**&**0011
0001
فقط جاهایی ۱ میماند که هر دو بیت ۱ باشند.
OR: |
0101**|**0011
0111
اگر حداقل یکی ۱ باشد، نتیجه ۱ است.
XOR: ^
0101**^**0011
0110
اگر دو بیت متفاوت باشند، نتیجه ۱ است.
NOT: ~
~0101
1010
در این مثال آموزشی ۴ بیتی، هر ۰ و ۱ برعکس میشود.
جمع و تفریق دودویی؛ بیت به بیت¶
جمع: ۵ + ۳ = ۸
0101
+ 0011
──────
1000قاعدهی پایه: ۱+۱ یعنی ۰ و ۱ انتقالی به ستون بعد.
تفریق: ۸ − ۳ = ۵
1000
− 0011
──────
0101اگر در یک ستون رقم بالایی کوچکتر باشد، از ستون سمت چپ قرض میگیریم؛ درست شبیه تفریق دهدهی.
شیفت هم جابهجایی واقعی بیتهاست:
0011**<< 1**0110۳ → ۶
0011**>> 1**0001۳ → ۱
ترفند ذهنی: برای فهم عملگرهای بیتی، همیشه عدد را به بیتها تبدیل کن، عملگر را ستونبهستون اجرا کن و در پایان دوباره به دهدهی برگردان.
مثال:
%%c
unsigned int a = 5; // 0101
unsigned int b = 3; // 0011
printf("%u\n", a & b); // 1 -> 0001
printf("%u\n", a | b); // 7 -> 0111
printf("%u\n", a ^ b); // 6 -> 0110کاربرد ساده: زوج یا فرد¶
کمارزشترین بیت یک عدد زوج 0 و یک عدد فرد 1 است:
%%c
int n = 13;
printf("%d\n", n & 1); // برای 13 خروجی 1شیفت و توانهای دو¶
برای اعداد unsigned و در محدودهی معتبر، شیفت چپ یک بیت اغلب معادل ضرب در ۲ و شیفت راست معادل تقسیم صحیح بر ۲ دیده میشود:
%%c
unsigned int x = 7;
printf("%u\n", x << 1); // 14هشدار علمی: قوانین شیفت برای مقادیر علامتدار و شیفتهای خارج از محدوده جزئیات مهمی دارند. برای مثالهای آموزشی بیتی،
unsignedمدل ذهنی امنتری است.
Bitmask چیست؟¶
گاهی هر بیت را بهعنوان یک «پرچم روشن/خاموش» استفاده میکنیم. به این الگو bitmask میگویند. این روش در مجوزهای فایل، رجیسترهای سختافزاری، پروتکلها و سیستمهای نهفته بسیار رایج است. در این درس فقط آشنایی با نام و ایده کافی است.
۵. اولویت (Precedence) و جهت وابستگی (Associativity) عملگرها¶
عبارت زیر را در نظر بگیرید:
%%c
int result = 2 + 3 * 4;چون * اولویت بیشتری از + دارد، نتیجه 14 است. اما هدف آموزشی مهمتر این است: در کد واقعی بهجای حفظکردن جدول بزرگ اولویتها، با پرانتز قصد خود را واضح کنید.
نمونهای که پرانتز خوانایی را نجات میدهد:
int ok = (age >= 18) && (hasId == 1);(نمایشی — این نمونه عمداً اجرا نمیشود)
چند نکتهی بسیار مهم:
=اولویت پایینتری از بسیاری از عملگرها دارد و با==اشتباه نشود.عملگرهای منطقی
&&و||از عملگرهای رابطهای پایینترند.عملگر شرطی سهتایی
?:در بخش کنترل جریان معرفی میشود؛ دانستن نامش در این مرحله کافی است.ترتیب اولویت با ترتیب واقعی ارزیابی operands یک چیز نیست؛ C در بعضی عبارتها ترتیب ارزیابی را تضمین نمیکند.
پنجرهی بیشتر: عبارتهایی مثل
i = i++ + ++i;نمونههای خوبی برای «کد ننویسید!» هستند. واردشدن به جزئیات sequence/ordering در این درس لازم نیست؛ پیام اصلی این است که یک متغیر را چندبار در یک عبارت پیچیده تغییر ندهید.
تمرین تشخیص اولویت¶
بدون اجرا، مقدار نهایی را پیشبینی کنید و سپس با پرانتز بازنویسی کنید:
%%c
int x = 2 + 3 * 4 > 10 && 5 % 2;جمعبندی و تمرینهای این بخش¶
printfبرای خروجی،scanfبرای ورودی (و اهمیت&)عملگرهای محاسباتی، رابطهای، منطقی
عملگرهای انتسابی کوتاه (
+=,-=, ...)
تمرین ۱ — بررسی دو عدد¶
برنامهای بنویسید که دو عدد از کاربر بگیرد و بررسی کند آیا هر دو مثبت هستند یا نه. در صورت مثبت بودن هر دو عدد، مجموع و باقیماندهی تقسیم آنها را چاپ کنید.
توجه: در این تمرین نباید از
ifوelseاستفاده کنید. هدف این است که با مفاهیم و عملگرهایی که تا اینجا یاد گرفتهاید، مسئله را حل کنید.
تمرین ۲ — سیستم بررسی PIN¶
یک برنامهی ساده برای ورود به یک سیستم بنویسید.
یک PIN ثابت مثل 1234 با استفاده از const تعریف کنید. سپس PIN را یک بار از کاربر بگیرید و بررسی کنید که آیا درست است یا نه. در پایان، نتیجهی مناسب را چاپ کنید؛ مثلاً «ورود موفق» یا «PIN اشتباه است».
توجه: در این تمرین نباید از
if،elseیا حلقه استفاده کنید. مسئله را فقط با مفاهیم و عملگرهایی که تا این بخش یاد گرفتهاید حل کنید.
تمرین ۳ — دستگاه خودپرداز (ATM)¶
یک مبلغ پول به ریال (مثلاً 870000 ریال) را از کاربر بگیرید و حساب کنید به چند اسکناس 100000 ریالی و چند اسکناس 10000 ریالی نیاز است.
هدف تمرین: استفادهی عملی از عملگرهای تقسیم (/)، باقیمانده (%) و عملگرهای انتسابی ترکیبی مثل /= و %=.
راهنمایی: ابتدا تعداد اسکناسهای
100000ریالی را با تقسیم به دست آورید. سپس با استفاده از%=مقدار باقیماندهی مبلغ را محاسبه کنید و از روی آن تعداد اسکناسهای10000ریالی را به دست آورید.
تمرین ۴ — تبدیل ثانیه به ساعت، دقیقه و ثانیه¶
عددی بهعنوان کل ثانیهها بگیرید (مثلاً 3725) و آن را به قالب ساعت:دقیقه:ثانیه چاپ کنید. فقط با / و % قابل حل است.
تمرین ۵ — تعویض مقدار دو متغیر بدون متغیر کمکی¶
دو عدد از کاربر بگیرید و مقدار آنها را بدون استفاده از یک متغیر سوم (کمکی) با هم جابهجا کنید و نتیجه را چاپ کنید.
تمرین ۶ — بررسی سال کبیسه¶
یک سال میلادی را از کاربر بگیرید و بررسی کنید که آیا کبیسه است یا نه. قاعدهی سال کبیسه در تقویم میلادی به این صورت است:
| شرط | نتیجه |
|---|---|
| بر ۴ بخشپذیر نباشد | کبیسه نیست |
| بر ۴ بخشپذیر باشد، ولی بر ۱۰۰ نه | کبیسه است |
| بر ۱۰۰ بخشپذیر باشد، ولی بر ۴۰۰ نه (مثل ۱۹۰۰) | کبیسه نیست |
| بر ۴۰۰ بخشپذیر باشد (مثل ۲۰۰۰) | کبیسه است |
نتیجه را فقط با عملگرهای %، &&، || و ! (بدون if) بهصورت ۰ یا ۱ چاپ کنید.
تمرین ۷ — کالبدشکافی خطاهای ورودی/خروجی¶
هر خط را مستقل بررسی کنید و مشخص کنید مشکل از نوع syntax، format mismatch، منطق یا محدودیت ورودی است:
%%c
int x;
double y;
char c;
scanf("%f", &y);
printf("%d\n", y);
scanf("%d", x);
scanf("%c", &c);سپس نسخهی صحیح را بنویسید و توضیح دهید چرا اصلاح شده است.
تمرین ۸ — Debug by Warning¶
کد زیر را با -Wall -Wextra کامپایل کنید و هشدارها را بخوانید:
%%c
#include <stdio.h>
int main(void) {
int count = 10;
double ratio = 3.7;
printf("count=%f ratio=%d\n", count, ratio);
return 0;
}بدون اجرای برنامه، از روی warningها مشکل را پیدا و اصلاح کنید.
تمرین ۹ — Decode یک بیتماسک ساده¶
سه قابلیت را با سه بیت در نظر بگیرید: خواندن = بیت 0، نوشتن = بیت 1، اجرا = بیت 2. اگر مقدار مجوز 5 باشد، با & مشخص کنید کدام قابلیتها روشناند. این تمرین مقدمهای کوچک برای درک مجوزهای سطح پایین و پرچمهاست.
تمرین ۱۰ — سؤال مفهومی کوتاه¶
برای هر عبارت فقط بگویید «ایمن و واضح»، «قابل اجرا ولی گمراهکننده»، یا «دارای رفتار تعریفنشده/نامعتبر» و دلیل بیاورید:
5 / 2
5.0 / 2
(double)(5 / 2)
(double)5 / 2
INT_MAX + 1(نمایشی — این نمونه عمداً اجرا نمیشود)
جدول ارزش منطقی در C¶
در C هر مقدار صحیح صفر در شرط، false و هر مقدار غیرصفر true در نظر گرفته میشود. عملگرهای مقایسهای و منطقی معمولاً نتیجهی 0 یا 1 تولید میکنند.
| A | B | A && B | A || B | |---:|---:|---:|---:| | 0 | 0 | 0 | 0 | | 0 | غیرصفر | 0 | 1 | | غیرصفر | 0 | 0 | 1 | | غیرصفر | غیرصفر | 1 | 1 |
این نکته توضیح میدهد چرا عبارتی مثل if (x) در C معنادار است؛ هرچند خود if در بخش کنترل جریان آموزش داده میشود.
char، ASCII و Unicode: یک تفاوت مهم¶
char یک واحد عدد صحیح کوچک است و برای ذخیرهی بایت/کاراکتر بهکار میرود. در مثالهای مقدماتی معمولاً از حروف ASCII مثل 'A' استفاده میکنیم؛ اما متن فارسی را نمیتوان با فرض «هر حرف = یک char» تحلیل کرد. متنهای Unicode معمولاً با رمزگذاریهایی مثل UTF-8 ذخیره میشوند و یک نویسهی فارسی ممکن است چند بایت اشغال کند.
پنجرهی بیشتر: تفاوت «character»، «byte»، «code point» و «encoding» موضوعی مهم در برنامهنویسی واقعی است. در این درس فقط لازم است بدانیم مدل سادهی ASCII برای همهی زبانهای طبیعی کافی نیست.
چند format specifier تکمیلی که بهتر است اسمشان را دیده باشید¶
| قالب | کاربرد متداول |
|---|---|
%u | unsigned int |
%ld | long |
%lld | long long |
%zu | size_t، مثلاً خروجی sizeof |
%p | آدرس؛ آرگومان معمولاً به (void*) تبدیل میشود |
%% | چاپ خود علامت % |
قالب اشتباه فقط یک مشکل ظاهری نیست. در توابع variadic مثل printf و scanf، ناهماهنگی format specifier با نوع آرگومان میتواند رفتار نادرست یا حتی Undefined Behavior ایجاد کند.
جمعبندی کلی بخش دوم¶
مرور نکات کلیدی کل بخش:
متغیرها و انواع داده:
int,float,double,char,bool، قواعد نامگذاری، بازهی مقادیر، overflow، ثابتها، تبدیل نوعورودی/خروجی:
printf/scanfو format specifierهاعملگرها: محاسباتی، رابطهای، منطقی، انتسابی، بیتی، و اولویت اجرای آنها
تمرین نهایی: برنامهای بنویسید که یک عدد صحیح از کاربر بگیرد و با استفاده از عملگر بیتی & مشخص کند زوج است یا فرد، سپس با استفاده از << مقدار آن را دو برابر کرده و چاپ کند.
منابع و مسیر مطالعهی بیشتر¶
Brian W. Kernighan & Dennis M. Ritchie, The C Programming Language (K&R) — مرجع کلاسیک زبان C.
CS50x, Week 1: C — نمونهای از شیوهی آموزش متغیرها، نوعها، عملگرها و کامپایل در یک درس مقدماتی علوم کامپیوتر.
cppreference: C language — مرجع فنی برای نوعها، تبدیلها، عملگرها و کتابخانهی استاندارد.
ISO C / compiler documentation — برای جزئیات دقیق رفتارهای تعریفشده، پیادهسازیوابسته و Undefined Behavior.
CSES Problem Set (cses.fi) — مجموعهی سؤالهای برنامهنویسی و الگوریتمی برای تمرین بیشتر؛ در انتخاب برخی تمرینهای این فایل، با اعمال تغییراتی، از آن کمک گرفته شده است.
ابزارهای هوش مصنوعی مثل Claude، ChatGPT و Gemini — برای پرسیدن توضیح بیشتر، مثال و رفع ابهام؛ پاسخهایشان را با منابع مرجع بالا و با اجرای واقعی کد بررسی کنید.
پیشنهاد به دانشجو: لازم نیست در شروع همهی این منابع را خطبهخط بخوانید. مهم است بدانید برای پرسشهای دقیقتر، منابع مرجع وجود دارند و بتوانید در زمان نیاز سراغشان بروید.
تیم تهیه و تدوین¶
اعضای تیم و تقسیم کار¶
| عضو تیم | نقش و مشارکت |
|---|---|
| ملیکا محمدبیگی | تهیهی پروتوتایپ و نسخهی اولیهی محتوا، شامل ساختار کلی مباحث و تمرینهای اولیه؛ همچنین طراحی اولیهی فایل تمرینها، و در ادامه ساخت دو فرمت دیگر از همین فایل تمرین و بررسی آنها برای اطمینان از یکسان بودن با فایل HTML اصلی |
| درسا عناصری | بازبینی علمی و ویرایشی، توسعه و بهینهسازی ساختار آموزشی، افزودن/حذف و بازطراحی تمرینها، افزودن نکات مفهومی و خطاهای رایج، و بررسی ایدههای آموزشی مورد استفاده در منابع و دورههای دانشگاهی معتبر؛ همچنین بررسی علمی فایل تمرینها، سنجش سختی سؤالها و ارتباط آنها با یکدیگر، یکسانسازی و مرتبسازی فایل تمرینها، اضافه و کم کردن چندین سؤال، و افزودن تذکرات و نکاتی برای استاد تدریسکننده در برخی سؤالها؛ و در پایان، تهیه و تدوین فایل نهایی |
| زینب قاراچشمه | بهبود و ارتقای محتوای کارگاه بر پایهی نسخهی اولیهی ملیکا محمدبیگی که پیشتر توسط درسا عناصری بررسی شده بود؛ بازبینی علمی محتوا بهصورت مشترک با درسا عناصری؛ همچنین کمک در یافتن نمونهسؤالها و تمرینهای خوب و مفهومی، از جمله از CSES، و اعمال تغییراتی روی آنها |
فرایند تولید و بازبینی¶
محتوا از یک نسخهی اولیه آغاز شد و سپس با تمرکز بر صحت علمی، پیوستگی پیشنیاز/پسنیاز، تناسب با دانشجوی ترم اول، تنوع مثالها، خطاهای رایج و تمرینهای تشخیصی توسعه یافت. در نسخهی حاضر محدودیت تعداد جلسه حذف شده تا مدرس بتواند بر اساس سطح کلاس و زمان واقعی، بین «هستهی اصلی» و «مطالب تکمیلی» انتخاب کند.
شفافیت دربارهی استفاده از هوش مصنوعی¶
برای شفافیت با خوانندگان این فایل، لازم است بگوییم که در تولید این مجموعه از ابزارهای هوش مصنوعی (AI) بهره گرفتهایم. این کمک در سه بخش بود:
ایدهگیریگرفتن پیشنهاد برای ساختار مباحث، مثالها و شیوهی توضیح مفاهیم.
تولید محتواکمک در نگارش پیشنویس بخشهایی از متن و مثالها.
بیشترین کمکتولید خود کدها و فرمتهاتولید کدهای HTML و فرمتهای Markdown و Jupyter Notebook، که بیشترین سهم کمک هوش مصنوعی در همین بخش بود.
با این حال، محتوای نهایی با نظارت انسانی خودِ ما، یعنی اعضای تیم تهیه و تدوین، بازبینی و تکمیل شده است.