-
فرشید پوشنده
1405/05/22
-
22 مرداد 1405
بازگشت به: آموزش برنامه نویسی c++ سی پلاس پلاس
۰.۲ — آشنایی با برنامهها و زبانهای برنامهنویسی
کامپیوترها چگونه کار میکنند؟
کامپیوترهای مدرن فوقالعاده سریع هستند و هر روز نیز سریعتر میشوند. با این حال، کامپیوترها محدودیتهای قابل توجهی نیز دارند: آنها به طور ذاتی فقط مجموعه محدودی از دستورات را میفهمند و باید دقیقاً به آنها گفته شود که چه کاری انجام دهند.
وقتی کامپیوتر در حال اجرای دستورات موجود در یک برنامه کامپیوتری است، میگوییم که برنامه در حال اجرا (Running) یا اجرایشدن (Executing) است. کامپیوتر تا زمانی که به آن دستور داده نشود، اجرای برنامه را آغاز نمیکند. این کار معمولاً نیاز دارد که کاربر برنامه را راهاندازی (Launch) کند، اگرچه ممکن است برنامهها توسط برنامههای دیگر نیز راهاندازی شوند.
برنامه کامپیوتری چیست؟
یک برنامه کامپیوتری، دنبالهای از دستورات است که به کامپیوتر میگوید چه اقداماتی را و به چه ترتیبی انجام دهد. برنامههای کامپیوتری معمولاً با استفاده از زبانهای برنامهنویسی نوشته میشوند. زبان برنامهنویسی، زبانی است که برای سهولت نوشتن دستورات برای کامپیوتر طراحی شده است.
زبانهای برنامهنویسی بسیار متنوعی در جهان وجود دارند که هر کدام برای نیازهای خاصی طراحی شدهاند. به عمل (و هنر) نوشتن یک برنامه، برنامهنویسی (Programming) میگویند. در درسهای آینده این فصل، به طور دقیقتری بررسی خواهیم کرد که چگونه میتوانیم با استفاده از زبان C++، برنامههای خود را بنویسیم.
سختافزار و نرمافزار
برنامهها روی سختافزار (Hardware) کامپیوتر اجرا میشوند که شامل اجزای فیزیکی تشکیلدهنده کامپیوتر است. اجزای مهم سختافزاری در یک دستگاه محاسباتی معمولی عبارتند از:
CPU (واحد پردازش مرکزی) که اغلب «مغز» کامپیوتر نامیده میشود و دستورات را اجرا میکند.
حافظه (Memory) که برنامههای کامپیوتری قبل از اجرا در آن بارگذاری میشوند.
دستگاههای تعاملی (مانند نمایشگر، صفحهلمسی، صفحهکلید یا ماوس) که به فرد امکان تعامل با کامپیوتر را میدهند.
دستگاههای ذخیرهسازی (مانند هارددیسک، SSD یا حافظه فلش) که اطلاعات (از جمله برنامههای نصبشده) را حتی زمانی که کامپیوتر خاموش است، نگهداری میکنند.
در مقابل، اصطلاح نرمافزار (Software) به طور گسترده به برنامههای موجود در یک سیستم اشاره دارد که برای اجرا روی سختافزار طراحی شدهاند.
پلتفرم چیست؟
در محاسبات مدرن، برنامهها اغلب با چیزی بیش از سختافزار تعامل دارند — آنها همچنین با نرمافزارهای دیگر روی سیستم (بهویژه سیستمعامل) تعامل دارند. اصطلاح پلتفرم (Platform) به مجموعه سازگاری از سختافزار و نرمافزار (سیستمعامل، مرورگر و غیره) اشاره دارد که محیطی برای اجرای نرمافزار فراهم میکند. برای مثال، اصطلاح «PC» معمولاً به معنای پلتفرمی است که شامل سیستمعامل ویندوز در حال اجرا روی یک CPU خانواده x86 است.
پلتفرمها اغلب خدمات مفیدی برای برنامههای در حال اجرا روی خود فراهم میکنند. برای مثال، یک برنامه دسکتاپ ممکن است از سیستمعامل درخواست کند که یک قطعه حافظه خالی در اختیارش قرار دهد، یک فایل در آنجا ایجاد کند یا یک صدا پخش کند. برنامه در حال اجرا نیازی به دانستن نحوه انجام این کارها ندارد.
اگر برنامهای از قابلیتها یا خدماتی استفاده کند که توسط پلتفرم ارائه شدهاند، به آن پلتفرم وابسته (Dependent) میشود و بدون تغییرات، روی پلتفرمهای دیگر قابل اجرا نیست. برنامهای که به راحتی از یک پلتفرم به پلتفرم دیگر منتقل شود، قابلانتقال (Portable) نامیده میشود. به عمل تغییر برنامه بهگونهای که روی پلتفرم متفاوتی اجرا شود، انتقال (Porting) میگویند.
زبان ماشین (Machine Language)
CPU کامپیوتر قادر به درک زبان C++ نیست. در عوض، CPUها فقط قادر به پردازش دستورات نوشتهشده به زبان ماشین (Machine Language) هستند. مجموعه تمام دستورات ممکن زبان ماشین که یک CPU خاص میتواند بفهمد، مجموعه دستورات (Instruction Set) نامیده میشود.
در اینجا یک نمونه دستور زبان ماشین آورده شده است:
10110000 01100001هر دستور توسط CPU به عنوان یک فرمان برای انجام یک کار بسیار خاص درک میشود، مانند «این دو عدد را مقایسه کن» یا «این عدد را در آن مکان حافظه کپی کن». در گذشتههای دور، برنامهنویسان مجبور بودند برنامهها را مستقیماً به زبان ماشین بنویسند که کاری بسیار دشوار و زمانبر بود.
نکات مهم درباره زبان ماشین:
۱. هر دستور از دنبالهای از ۱ و ۰ تشکیل شده است. هر ۰ یا ۱ منفرد، یک رقم دودویی یا به اختصار بیت (Bit) نامیده میشود. تعداد بیتهای یک دستور زبان ماشین متفاوت است — برای مثال، برخی CPUها دستوراتی با طول ۳۲ بیت پردازش میکنند، در حالی که برخی دیگر (مانند خانواده x86 که ممکن است از آن استفاده کنید) دستوراتی با طول متغیر دارند.
۲. هر خانواده از CPUهای سازگار (مانند x86، Arm64) زبان ماشین مخصوص خود را دارد و این زبان ماشین با زبان ماشین سایر خانوادههای CPU سازگار نیست. این بدان معناست که برنامههای زبان ماشین نوشتهشده برای یک خانواده CPU، روی CPUهای خانواده دیگر قابل اجرا نیستند!
زبانهای اسمبلی (Assembly Languages)
دستورات زبان ماشین (مانند 10110000 01100001) برای CPU ایدهآل هستند، اما برای انسانها دشوار است. از آنجایی که برنامهها (حداقل از نظر تاریخی) توسط انسانها نوشته و نگهداری میشوند، منطقی است که زبانهای برنامهنویسی با در نظر گرفتن نیازهای انسانی طراحی شوند.
یک زبان اسمبلی (Assembly Language) زبانی است که عملاً به عنوان یک زبان ماشین خوانا برای انسان عمل میکند. در اینجا همان دستور بالا به زبان اسمبلی x86 آورده شده است:
mov al, 0x61این دستور نشان میدهد که:
عملیات (کاری که دستور انجام میدهد) با یک نام کوتاه (معمولاً ۳ تا ۵ حرف) شناسایی میشود.
movبه راحتی به عنوان مخفف «حرکت» (Move) قابل درک است که عملیاتی برای کپی کردن بیتها از یک مکان به مکان دیگر است.ثباتها (Registers) که مکانهای حافظه سریع درون خود CPU هستند، با یک نام قابل دسترسی هستند.
alنام یک ثبات خاص روی CPU x86 است.اعداد را میتوان با فرمت راحتتری مشخص کرد. زبانهای اسمبلی معمولاً از اعداد اعشاری (مانند ۹۷) و اعداد هگزادسیمال (مانند
0x61) پشتیبانی میکنند.
درک این نکته که دستور اسمبلی mov al, 0x61 عدد هگزادسیمال 0x61 را در ثبات CPU با نام al کپی میکند، بسیار آسان است.
از آنجایی که CPUها زبان اسمبلی را نمیفهمند، برنامههای اسمبلی باید قبل از اجرا به زبان ماشین ترجمه شوند. این ترجمه توسط برنامهای به نام اسمبلر (Assembler) انجام میشود. از آنجایی که هر دستور زبان اسمبلی معمولاً برای انطباق با یک دستور معادل زبان ماشین طراحی شده است، فرآیند ترجمه معمولاً ساده است.
درست مانند هر خانواده CPU که زبان ماشین خاص خود را دارد، هر خانواده CPU نیز زبان اسمبلی خاص خود را دارد (که برای تبدیل شدن به زبان ماشین همان خانواده CPU طراحی شده است). این بدان معناست که زبانهای اسمبلی مختلفی وجود دارند. اگرچه از نظر مفهومی مشابه هستند، اما زبانهای اسمبلی مختلف از دستورات متفاوت، قراردادهای نامگذاری متفاوت و غیره پشتیبانی میکنند.
آشنایی با زبانهای سطح پایین (Low-Level Languages)
زبانهای ماشین و اسمبلی، زبانهای سطح پایین (Low-Level Languages) محسوب میشوند، زیرا این زبانها انتزاع (Abstraction) کمی از معماری ماشین ارائه میدهند. به عبارت دیگر، خود زبان برنامهنویسی متناسب با معماری مجموعه دستورات خاصی که قرار است روی آن اجرا شود، طراحی شده است.
معایب زبانهای سطح پایین:
برنامههای نوشتهشده به زبان سطح پایین، قابلانتقال (Portable) نیستند. از آنجایی که یک زبان سطح پایین متناسب با یک معماری مجموعه دستورات خاص طراحی شده است، برنامههای نوشتهشده به آن زبان نیز چنین هستند. انتقال چنین برنامههایی به معماریهای دیگر معمولاً کار سادهای نیست.
نوشتن برنامه به زبان سطح پایین نیاز به دانش دقیق از خود معماری دارد. برای مثال، دستور
mov al, 0x61نیاز دارد که بدانیمalبه یک ثبات CPU موجود در این پلتفرم خاص اشاره دارد و نحوه کار با آن ثبات را درک کنیم. در معماری دیگر، این ثبات ممکن است نام متفاوتی داشته باشد، محدودیتهای متفاوتی داشته باشد یا اصلاً وجود نداشته باشد.برنامههای سطح پایین درک دشواری دارند. اگرچه تکدستورهای اسمبلی میتوانند کاملاً قابلفهم باشند، اما همچنان استنباط اینکه یک بخش از کد اسمبلی واقعاً چه کاری انجام میدهد، دشوار است. و از آنجایی که برنامههای اسمبلی برای انجام حتی کارهای ساده به دستورات زیادی نیاز دارند، معمولاً طولانی هستند.
نوشتن برنامههای اسمبلی با پیچیدگی قابلتوجه دشوار است زیرا زبان فقط قابلیتهای ابتدایی را ارائه میدهد. برنامهنویس باید هر چیزی را که نیاز دارد، خودش پیادهسازی کند.
مزیت اصلی زبانهای سطح پایین این است که سریع هستند. امروزه نیز از اسمبلی در بخشهایی از کد که عملکرد در آنها حیاتی است، استفاده میشود.
آشنایی با زبانهای سطح بالا (High-Level Languages)
برای رفع بسیاری از معایب فوق، زبانهای برنامهنویسی جدید «سطح بالا» مانند C، C++، Pascal (و بعداً زبانهایی مانند Java، JavaScript و Perl) توسعه یافتند.
در اینجا همان دستور بالا به زبان C/C++ آورده شده است:
a = 97;درست مانند برنامههای اسمبلی (که باید به زبان ماشین تبدیل شوند)، برنامههای نوشتهشده به زبان سطح بالا نیز باید قبل از اجرا به زبان ماشین ترجمه شوند. دو روش اصلی برای این کار وجود دارد: کامپایل (Compiling) و تفسیر (Interpreting).
برنامههای C++ معمولاً کامپایل میشوند. یک کامپایلر (Compiler) برنامهای (یا مجموعهای از برنامهها) است که کد منبع یک زبان (معمولاً یک زبان سطح بالا) را خوانده و آن را به زبان دیگری (معمولاً یک زبان سطح پایین) ترجمه میکند. برای مثال، یک کامپایلر C++، کد منبع C++ را به کد ماشین ترجمه میکند.
خروجی کد ماشین توسط کامپایلر سپس میتواند در یک فایل اجرایی (Executable File) (حاوی دستورات زبان ماشین) بستهبندی شود که میتواند به دیگران توزیع شود و توسط سیستمعامل اجرا شود. قابلتوجه است که اجرای فایل اجرایی نیازی به نصب کامپایلر ندارد.
در ابتدا، کامپایلرها ابتدایی بودند و کد اسمبلی یا ماشین کند و بهینهنشده تولید میکردند. اما در طول سالها، کامپایلرها در تولید کد سریع و بهینه بسیار ماهر شدهاند و در برخی موارد میتوانند بهتر از انسانها عمل کنند!
مزایای زبانهای سطح بالا:
زبانهای سطح بالا به این دلیل چنین نامیدهشدهاند که سطح انتزاع بالایی از معماری زیرین ارائه میدهند.
دستور a = 97; را در نظر بگیرید. این دستور به ما امکان میدهد مقدار ۹۷ را در جایی از حافظه ذخیره کنیم، بدون اینکه نیاز باشد بدانیم دقیقاً آن مقدار در کجا قرار میگیرد یا چه دستور خاصی از کد ماشین توسط CPU برای ذخیره آن مقدار نیاز است. در واقع، هیچ چیز وابسته به پلتفرم خاصی در این دستور وجود ندارد. کامپایلر تمام کارها را انجام میدهد تا بفهمد چگونه این دستور C++ به کد ماشین مختص پلتفرم تبدیل شود.
زبانهای سطح بالا به برنامهنویسان اجازه میدهند بدون دانش زیاد درباره پلتفرمی که قرار است برنامه روی آن اجرا شود، برنامه بنویسند. این نه تنها نوشتن برنامهها را آسانتر میکند، بلکه آنها را به طور قابلتوجهی قابلانتقالتر (More Portable) نیز میسازد. اگر دقت کنیم، میتوانیم یک برنامه C++ بنویسیم که روی هر پلتفرمی که کامپایلر C++ دارد، کامپایل شود! برنامهای که برای اجرا روی چندین پلتفرم طراحی شده است، چندسکویی (Cross-Platform) نامیده میشود.
سایر مزایای زبانهای سطح بالا:
برنامههای نوشتهشده به زبان سطح بالا، خواندن، نوشتن و یادگیری آسانتری دارند زیرا دستورات آنها بیشتر به زبان طبیعی و ریاضیاتی که ما هر روز استفاده میکنیم، شباهت دارند. در بسیاری از موارد، زبانهای سطح بالا برای انجام کارهای مشابه به دستورات کمتری نسبت به زبانهای سطح پایین نیاز دارند. برای مثال، در C++ میتوانید
a = b * 2 + 5;را در یک خط بنویسید. در زبان اسمبلی، این کار به ۴ تا ۶ دستور متفاوت نیاز دارد. این باعث میشود برنامههای نوشتهشده با زبانهای سطح بالا مختصرتر باشند که درک آنها را آسانتر میکند.زبانهای سطح بالا معمولاً شامل قابلیتهای اضافی هستند که انجام کارهای رایج برنامهنویسی را آسانتر میکنند، مانند درخواست یک بلوک حافظه یا دستکاری متن. برای مثال، فقط یک دستور لازم است تا مشخص شود آیا کاراکترهای «abc» در یک بلوک بزرگ از متن وجود دارند یا خیر (و اگر وجود دارند، چند کاراکتر باید بررسی شود تا «abc» پیدا شود). این میتواند پیچیدگی و زمان توسعه را به طور چشمگیری کاهش دهد.
نکته پایانی درباره سطح زبان C++
اگرچه C++ از نظر فنی یک زبان سطح بالا محسوب میشود، اما زبانهای برنامهنویسی جدیدتر (مانند زبانهای اسکریپتنویسی) سطح انتزاع بالاتری را ارائه میدهند. در نتیجه، گاهی C++ در مقایسه با آنها بهنادرست «زبان سطح پایین» نامیده میشود.
در واقع، امروزه C++ را میتوان بهطور دقیقتری به عنوان یک زبان سطح متوسط (Mid-Level Language) توصیف کرد. با این حال، این موضوع یکی از نقاط قوت کلیدی C++ را نیز برجسته میکند: توانایی کار در سطوح مختلف انتزاع. شما میتوانید برای عملکرد و دقت بهتر، در سطح پایینتری کار کنید، یا برای راحتی و سادگی بیشتر، در سطح بالاتری عمل کنید.
قوانین، بهترین روشها و هشدارها
در ادامه این آموزشها، نکات مهم بسیاری را در سه دسته زیر برجسته خواهیم کرد:
قانون (Rule)
قوانین، دستورالعملهایی هستند که باید انجام دهید، زیرا زبان به آنها نیاز دارد. عدم رعایت یک قانون معمولاً منجر به کار نکردن برنامه شما میشود.
بهترین روش (Best Practice)
بهترین روشها، کارهایی هستند که باید انجام دهید، زیرا آن روش انجام کار یا مرسوم (مرسومترین) است یا توصیه میشود. یعنی یا همه آن را به آن روش انجام میدهند (و اگر غیر از آن عمل کنید، کاری خلاف انتظار انجام دادهاید) یا به طور کلی برتر از سایر روشهاست.
هشدار (Warning)
هشدارها، کارهایی هستند که نباید انجام دهید، زیرا معمولاً منجر به نتایج غیرمنتظره میشوند.
خلاصه درس
برنامه کامپیوتری دنبالهای از دستورات برای انجام کارهای مشخص است.
زبان برنامهنویسی ابزاری برای نوشتن این دستورات به صورت قابلفهم برای انسان است.
سختافزار شامل CPU، حافظه، دستگاههای تعاملی و ذخیرهسازی است.
نرمافزار به برنامههایی گفته میشود که روی سختافزار اجرا میشوند.
پلتفرم مجموعه سازگاری از سختافزار و نرمافزار است.
زبان ماشین زبان اصلی CPU است و از ۰ و ۱ تشکیل شده است.
زبان اسمبلی نسخه قابلخواندنتر زبان ماشین است.
زبانهای سطح پایین سریع اما غیرقابلانتقال و دشوار هستند.
زبانهای سطح بالا قابلانتقال، خوانا و آسانتر هستند.
برنامههای C++ معمولاً کامپایل میشوند.
C++ یک زبان سطح متوسط با قابلیت کار در سطوح مختلف انتزاع است.
کدنویسم را همراه خود داشته باشید تا در درس بعدی، با تاریخچه زبان C++ و دلایل محبوبیت آن آشنا شوید. 🚀