سطوح زبان
منظور از سطح زبان، نزدیک بودن قواعد نگارشی آن به زبان آدمیست. مثلا C، پایتون زبانهای سطح بالایی هستند. در مقابل زبانهای سطح پایین وجود دارند. زبانهایی که قواعد نگارشیشون به زبان ماشین نزدیک تر است.
یک نمونه براتون مثال میزنم. چاپ Hello World در خروجی به سه زبان C و اسمبلی و ماشین.
در زبان C:
1 |
printf("Hello world"); |
در زبان اسمبلی:
1 2 3 4 5 6 7 8 9 10 11 |
global _main extern _printf section .text _main: push message call _printf add esp, 4 ret message: db 'Hello, World', 10, 0 |
و در زبان ماشین به این صورته:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
b8 21 0a 00 00 a3 0c 10 00 06 b8 6f 72 6c 64 a3 08 10 00 06 b8 6f 2c 20 57 a3 04 10 00 06 b8 48 65 6c 6c a3 00 10 00 06 b9 00 10 00 06 ba 10 00 00 00 bb 01 00 00 00 b8 04 00 00 00 cd 80 b8 01 00 00 00 cd 80 |
همونطور که میبینید نوشتن برنامه در این زبانها قدری سخت تر و زمانگیرتره. زبانهای سطح بالا نیز در آخر کار باید به چنین شکلی در بیان تا برای ماشین(پردازنده) قابل فهم و اجرا باشن. این کار رو کامپایلر انجام میده. کامپایلر در حقیقت یک مفسره که کدهای ما رو برای ماشین تفسیر میکنه. اما در حقیقت کامپایلرهای امروزی فراتر از یک مفسر هستند. چرا که علاوه بر تفسیر کدهای منبع، کار لینک کردن(توضیح خواهیم داد) و عیب یابی را نیز انجام میدهند. پس کامپایلر برنامه ایست که کدهای منبع ما را در زبانهای سطح بالایی چون C به زبانی قابل فهم برای ماشین تفسیر میکند و ازون یه خروجی ماشینی قابل اجرا میسازد. یک مسئله ای که بسیاری از ما با اون مشکل داریم تفاوت زبانهای کامپایلی و مفسریه . بعضی زبانها مفسر دارند و بصورت real-time ترجمه میشن. یکبار برای همیشه اینجا عرضتون میکنم. زبانهایی که مفسر دارن مانند پایتون، برای هربار اجرا باید مفسر از قبل بر روی سیستمشون نصب شده باشه. مفسر بصورت خط به خط از بالا به پایین کار میکنه. یعنی اگر شما یه برنامه پایتون داشته باشید که در اون باید از کاربر ورودی بگیره تا اون ورودی رو نگیره خط بعد ترجمه نمیشه و مفسر همونجا باقی خواهد ماند. پس میتونیم بفهمیم که اگر برنامه تا خط اخر درست نوشته شده باشه ولی خط اخر نادرست باشه برنامه تا اون خط بی مشکل پیش میره اما در خط آخر به شما خطا خواهد داد. اما در کامپایلر قضیه فرق میکنه. اولا برنامه ای که کامپایل میشه باید تمام و کمال درست نوشته شده باشه (از لحاظ دستور زبان یا syntax اون زبان). ثانیا برنامه ای که کامپایل شد، برای اجر نیازی به کامپایلر نخواهد داشت. مورد بعدی اینه که زبانهایی که کامپایلر دارند وابسته به سیستم عامل هستند. مثال بارزش اینکه شما نمیتونید فایل با پسوند exe رو از ویندوز بیارید و در گنو/لینوکس یا هر اکوسیستم غیر مایکروسافتی اجرا کنید. به همین دلیله که برای طیف وسیعی از اکوسیستم ها کامپایلرهای زبان C نوشته شده است. و اینم مجددا عرض کنم که پورتابل بودن زبان به معنی پورتابل بودن سورس برنامه است نه فایل ماشینی.
کامپایلرهای زیادی برای زبان C وجود دارن که از معروفترین آنها میتوان به Clang و GCC اشاره کرد. ما در این تاپیک از GCC استفاده میکنیم. در استفاده از کامپایلرها هیچ اجباری به نوع خاصی از کامپایلر نیست. کامپایلر باید دو ویژگی داشته باشه. اول اینکه مطابق با آخرین استانداردهای روز باشه و دوم اینکه مستندات خوبی رو ارائه بده. که مجموعه کامپایلرهای گنو چنین ویژگی رو دارند.
ادیتور
مبحث بعدی ادیتور یا ویرایشگر متن هست. جایی که ما بتونیم کدهامون رو درش بنویسیم. در استفاده از یک ادیتور هیچ اجباری نیست. اما ادیتور باید یک ویژگی داشته باشه و اون نیفزودن فراداده یا metadata به کد باشه. به چه صورت؟ به این معنی که ادیتور نباید هیچ نوع داده ای رو به کد نظیر پاراگراف، فرمت، افزونه، شماره خط و امثال اینها رو به کدهای ما اضافه کنه. سعی کنید از ادیتورهای ساده مانند TextEdit در مک، gedit، nano، vi وkate در گنو/لینوکس یا notepad در Microsoft Windows استفاده کنید. به هر صورت با جستجویی ساده در وب میتونید مناسب ترین ادیتور رو برای خودتون پیدا کنید.
من از sublime استفاده میکنم که البته آزاد نیست.
IDE یا محیط توسعه مجتمع
برنامه ای که کلیه امکانات لازم برای برنامهنویسی را در یک جا جمع کرده است. IDE ها از یک ادیتور، کامپایلر توکار، لینکر و عیب یاب تشکیل شده اند. میتوان بدون IDE هم برنامه نوشت و اتفاقا ترجیح من به کسانی که تازه شروع به برنامه نویسی میکنند این است که از IDE استفاده نکنند. به این دلیل که استفاده از IDE برنامه نویس مبتندی رو تنبل بار میاره. قضیه برای برنامه نویسهای صنعتی و کهنه کار فرق میکنه. اونا مسیرشون رو رفتن و IDE برای سرعت دادن به کارهاشونه و اینگونه نیست که اگر IDE رو ازشون بگیرید فلج بشن. بلکه خیلی هم خوب به کارهاشون میرسن. شما هم روزی حرفه ای میشید و میتونید از IDE استفاده کنید. کسی که تازه شروع به برنامه نویسی میکنه خوبه که با انواع ادیتورها و کامپایلرها و خط فرمان آشنا بشه. خوبه که از قابلیت autocomplete استفاده نکنید و بیشتر با دستهاتون کد بزنید حتی کدهای بسار تکراری. ازین جهت که اولا همین اول باید یاد بگیرید که برنامه نویسی آدم پر حوصلهای میخواد که نباید غز بزنه. مورد بعد اینکه دستهاتون عادت کنه به تند نویسی و دقیق نویسی. یاد بگیرید چگونه در محیط خط فرمان از کامپایلر و عیب یاب استفاده کنید. سویچ ها و فلگهای کامپایلرتون رو بشناسید. از خطاهای املایی نترسید. حرفه ای ترین برنامه نویس های دنیا هم دچار اشتباهات تایپی میشن.
ولی به هرحال اگر چنانچه توصیه های من رو نپذیرفتید تعدادی از IDE ها رو خدمتتون عرض میکنم:
و هرچیزی که شما میشناسید و من نمیشناسم.
ما در این تاپیک از ادیتور و مجموعه کامپایلرهای گنو بعلاوه ترمینال در سیستم عامل گنو/لینوکس استفاده میکنیم.
برنامه های که کاربران گنو/لینوکس باید نصب کنند:
یک ادیتور که باهاش راحتید.
یک کامپایلر ترجیحا gcc.
دیباگر gdb. اگر نصب نشده بود نصبش کنید.
و یک شبیه ساز ترمینال (Konsole, gnome-terminal, xfce4-terminal, Terminator, Tilda, Xterm یا هرچی که مناسبتونه).
شیوه کار با gcc در ترمینال بدین صورته:
1 |
$ gcc filename.c -o filename |
با این دستور، gcc فایل برنامه رو که به زبان C است از شما گرفته و در همان پوشه/دایرکتوری یک فایل اجرایی(ماشینی) با همون نام براتون میسازه.
اگر gcc را به این شکل به کار ببرید:
$ gcc filename.c
یک فایل اجرایی با نام a.out برای شما میسازه. حالا چرا a.out ؟
این یک بحث تاریخیه. در اون زمان که سیستم عامل یونیکس رو در آزمایشگاه های Bell متعلق به شرکت AT&T میساختن، کن تامسون ازین نام و فرمت خروجی که مخفف assembler output بود استفاده کرد. چون کد منبع به زبان اسمبلی ترجمه میشد و assembler نیز همین کد اسمبلی را به کد ماشینی ترجمه میکرد. در نظر داشته باشید که زبان اسمبلی با زبان ماشین تفاوت دارد. زبان ماشین فقط ۰ و ۱ است. بعدها همین مخفف در سیستمهای یونیکسی و BSD ها دست نخورده و تا امروز باقی ماند.
به هر حال شما باید قادر باشید فایلی رو که بعنوان خروجی گرفتید اجرا کنید. برای اینکار دو روش پیش رو دارید
اگر دایرکتوری محتوی فایل اجرایی در لیست مسیرهای تعریف شده قرار دارد
1 |
$ filename یا $ a.out |
اگر دایرکتوری یا پوشه شما در لیست مسیرهای سیستم عاملتون قرار ندارد:
1 |
$ ./filename یا $ ./a.out |