Giới thiệu về Ngôn ngữ lập trình
Máy tính hiện đại cực kỳ nhanh và ngày càng nhanh hơn. Tuy nhiên, máy tính cũng có một số hạn chế đáng kể: chúng chỉ hiểu được một số lệnh giới hạn và phải được chỉ dẫn chính xác phải làm gì.
Một chương trình máy tính (thường được gọi là ứng dụng ) là một tập hợp các lệnh mà máy tính có thể thực hiện để thực hiện một số tác vụ. Quá trình tạo ra một chương trình được gọi là lập trình . Các lập trình viên thường tạo ra các chương trình bằng cách tạo mã nguồn (thường được viết tắt là code ), là danh sách các lệnh được nhập vào một hoặc nhiều tệp văn bản.
Tập hợp các bộ phận máy tính vật lý tạo nên máy tính và thực thi chương trình được gọi là phần cứng . Khi một chương trình máy tính được tải vào bộ nhớ và phần cứng thực thi tuần tự từng lệnh, thì đây được gọi là chạy hoặc thực thi chương trình.
Ngôn ngữ máy
CPU của máy tính không có khả năng nói C++. Bộ lệnh giới hạn mà CPU có thể hiểu trực tiếp được gọi là mã máy (hoặc ngôn ngữ máy hoặc bộ lệnh ).
Sau đây là một ví dụ về hướng dẫn ngôn ngữ máy:10110000 01100001
Trở lại thời điểm máy tính mới được phát minh, các lập trình viên phải viết chương trình trực tiếp bằng ngôn ngữ máy, đây là việc rất khó khăn và tốn thời gian.
Cách thức tổ chức các lệnh này nằm ngoài phạm vi của phần giới thiệu này, nhưng điều thú vị là cần lưu ý hai điều. Đầu tiên, mỗi lệnh bao gồm một chuỗi các số 1 và 0. Mỗi số 0 hoặc 1 riêng lẻ được gọi là một chữ số nhị phân , hay gọi tắt là bit . Số bit tạo nên một lệnh duy nhất thay đổi — ví dụ, một số CPU xử lý các lệnh luôn dài 32 bit, trong khi một số CPU khác (như họ x86/x64 mà bạn có thể đang sử dụng) có các lệnh có thể có độ dài thay đổi.
Thứ hai, mỗi bộ số nhị phân được CPU diễn giải thành một lệnh để thực hiện một công việc rất cụ thể, chẳng hạn như so sánh hai số này hoặc đưa số này vào vị trí bộ nhớ đó . Tuy nhiên, vì các CPU khác nhau có các tập lệnh khác nhau, nên các lệnh được viết cho một loại CPU không thể được sử dụng trên một CPU không chia sẻ cùng một tập lệnh. Điều này có nghĩa là các chương trình thường không thể di chuyển (có thể sử dụng mà không cần chỉnh sửa lại nhiều) sang các loại hệ thống khác nhau và phải được viết lại hoàn toàn.
Ngôn ngữ lắp ráp
Vì ngôn ngữ máy rất khó để con người đọc và hiểu, nên ngôn ngữ lắp ráp đã được phát minh. Trong ngôn ngữ lắp ráp, mỗi lệnh được xác định bằng một chữ viết tắt ngắn (thay vì một tập hợp các bit) và có thể sử dụng tên và các số khác.
Sau đây là hướng dẫn tương tự như trên bằng ngôn ngữ lắp ráp:mov al, 061h
Điều này làm cho assembly dễ đọc và viết hơn nhiều so với ngôn ngữ máy. Tuy nhiên, CPU không thể hiểu trực tiếp ngôn ngữ assembly. Thay vào đó, chương trình assembly phải được dịch sang ngôn ngữ máy trước khi máy tính có thể thực thi. Điều này được thực hiện bằng cách sử dụng một chương trình gọi là assembler . Các chương trình được viết bằng ngôn ngữ assembly có xu hướng rất nhanh và assembly vẫn được sử dụng ngày nay khi tốc độ là yếu tố quan trọng.
Tuy nhiên, assembly vẫn có một số nhược điểm. Đầu tiên, ngôn ngữ assembly vẫn cần rất nhiều lệnh để thực hiện ngay cả những tác vụ đơn giản. Mặc dù bản thân các lệnh riêng lẻ có thể đọc được bằng con người, nhưng việc hiểu toàn bộ chương trình đang làm gì có thể là một thách thức (giống như cố gắng hiểu một câu bằng cách xem từng chữ cái riêng lẻ). Thứ hai, ngôn ngữ assembly vẫn không dễ di chuyển — một chương trình được viết bằng assembly cho một CPU có thể sẽ không hoạt động trên phần cứng sử dụng một tập lệnh khác và sẽ phải viết lại hoặc sửa đổi rộng rãi.
Ngôn ngữ cấp cao
Để giải quyết các mối quan tâm về khả năng đọc và tính di động, các ngôn ngữ lập trình mới như C, C++, Pascal (và sau đó là các ngôn ngữ như Java, Javascript và Perl) đã được phát triển. Các ngôn ngữ này được gọi là ngôn ngữ cấp cao , vì chúng được thiết kế để cho phép lập trình viên viết chương trình mà không cần phải quan tâm đến loại máy tính nào sẽ chạy chương trình.
Sau đây là hướng dẫn tương tự như trên trong C/C++:a = 97;
Giống như chương trình lắp ráp, chương trình được viết bằng ngôn ngữ cấp cao phải được dịch sang định dạng mà máy tính có thể hiểu được trước khi có thể chạy. Có hai cách chính để thực hiện việc này: biên dịch và thông dịch.
Trình biên dịch là một chương trình (hoặc tập hợp các chương trình) đọc mã nguồn (thường được viết bằng ngôn ngữ cấp cao) và dịch nó sang một ngôn ngữ khác (thường là ngôn ngữ cấp thấp, chẳng hạn như ngôn ngữ lắp ráp hoặc ngôn ngữ máy, v.v.). Thông thường, các tệp ngôn ngữ cấp thấp này sau đó được kết hợp thành một tệp thực thi (chứa các hướng dẫn ngôn ngữ máy) có thể chạy hoặc phân phối cho người khác. Đáng chú ý là việc chạy tệp thực thi không yêu cầu phải cài đặt trình biên dịch.
Ban đầu, trình biên dịch còn thô sơ và tạo ra mã chậm, không được tối ưu hóa. Tuy nhiên, qua nhiều năm, trình biên dịch đã trở nên rất giỏi trong việc tạo ra mã nhanh, được tối ưu hóa và trong một số trường hợp có thể làm tốt hơn con người trong ngôn ngữ lắp ráp!
Sau đây là mô tả đơn giản về quá trình biên dịch:
Vì các chương trình C++ thường được biên dịch nên chúng ta sẽ tìm hiểu chi tiết hơn về trình biên dịch C++ sau đây.
Trình thông dịch là chương trình thực hiện trực tiếp các lệnh trong mã nguồn mà không cần phải biên dịch chúng thành tệp thực thi trước. Trình thông dịch có xu hướng linh hoạt hơn trình biên dịch, nhưng kém hiệu quả hơn khi chạy chương trình vì quá trình thông dịch cần được thực hiện mỗi khi chương trình được chạy. Điều này cũng có nghĩa là trình thông dịch phải được cài đặt trên mọi máy nơi chương trình được thông dịch sẽ chạy.
Sau đây là bản trình bày đơn giản về quá trình diễn giải:
Hầu hết các ngôn ngữ đều có thể được biên dịch hoặc thông dịch. Theo truyền thống, các ngôn ngữ như C, C++ và Pascal được biên dịch, trong khi các ngôn ngữ “scripting” như Perl và Javascript có xu hướng được thông dịch. Một số ngôn ngữ, như Java, sử dụng kết hợp cả hai.
Ngôn ngữ cấp cao có nhiều đặc tính mong muốn.
Đầu tiên, ngôn ngữ cấp cao dễ đọc và viết hơn nhiều vì các lệnh gần với ngôn ngữ tự nhiên mà chúng ta sử dụng hàng ngày. Thứ hai, ngôn ngữ cấp cao yêu cầu ít lệnh hơn để thực hiện cùng một nhiệm vụ như ngôn ngữ cấp thấp, giúp chương trình ngắn gọn hơn và dễ hiểu hơn. Trong C++, bạn có thể làm một việc gì đó a = b * 2 + 5;trong một dòng. Trong ngôn ngữ lắp ráp, điều này sẽ cần 5 hoặc 6 lệnh khác nhau.
Thứ ba, chương trình có thể được biên dịch (hoặc diễn giải) cho nhiều hệ thống khác nhau và bạn không cần phải thay đổi chương trình để chạy trên các CPU khác nhau (bạn chỉ cần biên dịch lại cho CPU đó). Ví dụ:
Có hai ngoại lệ chung về tính di động.
Đầu tiên là nhiều hệ điều hành, chẳng hạn như Microsoft Windows, có các khả năng dành riêng cho nền tảng mà bạn có thể sử dụng trong mã của mình. Những khả năng này có thể giúp viết chương trình cho một hệ điều hành cụ thể dễ dàng hơn nhiều, nhưng phải đánh đổi bằng tính di động. Trong các hướng dẫn này, chúng ta sẽ tránh bất kỳ mã dành riêng cho nền tảng nào.
Thứ hai là một số trình biên dịch cũng hỗ trợ các tiện ích mở rộng dành riêng cho trình biên dịch — nếu bạn sử dụng những tiện ích này, các chương trình của bạn sẽ không thể được biên dịch bởi các trình biên dịch khác không hỗ trợ cùng tiện ích mở rộng mà không cần sửa đổi. Chúng ta sẽ nói thêm về những tiện ích này sau, khi bạn đã cài đặt trình biên dịch.
Quy tắc, Thực hành tốt nhất và cảnh báo
Khi thực hiện các hướng dẫn này, chúng tôi sẽ nêu bật nhiều điểm quan trọng theo ba danh mục sau: