Ngôn ngữ lập trình
|
Bài
viết
hoặc
đoạn
này
cần
thêm
chú
thích
nguồn
gốc
để
có
thể
kiểm
chứng
thông
tin. Những nội dung không có nguồn có thể bị đặt vấn đề và xóa bỏ. Mời bạn bổ sung chú thích từ các nguồn đáng tin cậy để giúp cải thiện bài viết. |
Ngôn ngữ lập trình là một tập con của ngôn ngữ máy tính, được thiết kế và chuẩn hóa để truyền các chỉ thị cho các máy có bộ xử lý (CPU), nói riêng là máy tính. Ngôn ngữ lập trình được dùng để lập trình máy tính, tạo ra các chương trình máy nhằm mục đích điều khiển máy tính hoặc mô tả các thuật toán để người khác đọc hiểu.
Mục lục
Định nghĩa[sửa]
Trước hết dạng chương trình duy nhất mà máy tính có thể thực thi trực tiếp là ngôn ngữ máy hay mã máy. Nó có dạng dãy các số nhị phân, thường được ghép nhóm thành byte 8 bit cho các hệ xử lý 8/16/32/64 bit [note 1]. Nội dung byte thường biểu diễn bằng đôi số hex. Để có được bộ mã này ngày nay người ta dùng ngôn ngữ lập trình để viết ra chương trình ở dạng văn bản và dùng trình dịch để chuyển sang mã máy [1].
Khi kỹ thuật điện toán ra đời chưa có ngôn ngữ lập trình dạng đại diện nào, thì phải lập trình trực tiếp bằng mã máy. Dãy byte viết ra được đục lỗ lên phiếu đục lỗ (punched card) và nhập qua máy đọc phiếu tới máy tính [2]. Sau đó chương trình có thể được ghi vào băng/đĩa từ để sau này nhập nhanh vào máy tính. Ngôn ngữ máy được gọi là "ngôn ngữ lập trình thế hệ 1" (1GL, first-generation programming languages) [3].
Sau đó các mã lệnh được thay thế bằng các tên gợi nhớ và trình được lập ở dạng văn bản (text) rồi dịch sang mã máy. Hợp ngữ (assembly languages) ra đời, là "ngôn ngữ lập trình thế hệ 2" (2GL, second-generation programming languages). Lập trình thuận lợi hơn, khi dịch có thể liên kết với thư viện chương trình con ở cả dạng macro (đoạn chưa dịch) và lẫn mã đã dịch. Hợp ngữ hiện được dùng là ngôn ngữ bậc thấp (low-level programming languages) để tinh chỉnh ngôn ngữ bậc cao thực hiện truy nhập trực tiếp phần cứng cụ thể trong việc lập trình hệ thống, tạo các hiệu ứng đặc biệt cho chương trình.
Ngôn ngữ bậc cao (high-level programming languages) hay "ngôn ngữ lập trình thế hệ 3" (3GL, third-generation programming languages) ra đời vào những năm 1950. Đây là các ngôn ngữ hình thức, dùng trong lập trình máy điện toán và không lệ thuộc vào hệ máy tính cụ thể nào. Nó giải phóng người lập trình ứng dụng làm việc trong hệ điều hành xác định mà không phải quan tâm đến phần cứng cụ thể. Các ngôn ngữ được phát triển liên tục với các dạng và biến thể mới, theo bước phát triển của kỹ thuật điện toán [4].
Đối với ngôn ngữ bậc cao thì định nghĩa ngôn ngữ lập trình theo [Loud 94], T.3 là:
- Ngôn ngữ lập trình là một hệ thống được ký hiệu hóa để miêu tả những tính toán (qua máy tính) trong một dạng mà cả con người và máy đều có thể đọc và hiểu được.
Theo định nghĩa ở trên thì một ngôn ngữ lập trình phải thỏa mãn được hai điều kiện cơ bản sau:
- Dễ hiểu và dễ sử dụng đối với người lập trình, để có thể dùng để giải quyết nhiều bài toán khác nhau.
- Miêu tả một cách đầy đủ và rõ ràng các tiến trình (tiếng Anh: process), để chạy được trên các hệ máy tính khác nhau.
Một tập hợp các chỉ thị được biểu thị qua ngôn ngữ lập trình nhằm mục đích thực hiện các thao tác máy tính nào đó được gọi là một chương trình. Khái niệm này còn có những tên khác như chương trình máy tính hay chương trình điện toán.
Lưu ý: chương trình được viết cho máy vi tính thường được gọi là phần mềm máy tính. Ví dụ: chương trình Microsoft Word là một cách gọi chung chung; cách gọi phần mềm Microsoft Word chỉ rõ hơn nó là một chương trình ứng dụng.
Khái niệm lập trình dùng để chỉ quá trình con người tạo ra chương trình máy tính thông qua ngôn ngữ lập trình. Người ta còn gọi đó là quá trình mã hoá thông tin tự nhiên thành ngôn ngữ máy. Từ viết mã cũng được dùng trong nhiều trường hợp để chỉ cùng một ý.
Như vậy, theo định nghĩa, mỗi ngôn ngữ lập trình cũng chính là một chương trình, nhưng nó có thể được dùng để tạo nên các chương trình khác. Văn bản được viết bằng ngôn ngữ lập trình để tạo nên chương trình được gọi là mã nguồn.
Thao tác chuyển đổi từ mã nguồn thành chuỗi các chỉ thị máy tính được thực hiện tương tự như việc chuyển đổi qua lại giữa các ngôn ngữ tự nhiên của con người. Các thao tác này gọi là biên dịch, hay ngắn gọn hơn là dịch. Nếu quá trình dịch diễn ra đồng thời với quá trình thực thi, ta gọi đó là thông dịch; nếu diễn ra trước, ta gọi đó là biên dịch. Phần mềm dịch tương ứng được gọi là phần mềm thông dịch và phần mềm biên dịch.
- Một phần mềm thông dịch là một phần mềm có khả năng đọc, chuyển mã nguồn của một ngôn ngữ và ra lệnh cho máy tính tiến hành các tính toán dựa theo cú pháp của ngôn ngữ.
-
Một
phần
mềm
biên
dịch
hay
ngắn
gọn
hơn
trình
biên
dịch
là
phần
mềm
có
khả
năng
chuyển
mã
nguồn
của
một
ngôn
ngữ
ban
đầu
sang
dạng
mã
mới
thường
là
một
ngôn
ngữ
cấp
thấp
hơn.
Ngôn ngữ cấp thấp nhất là một chuỗi các chỉ thị máy tính mà có thể được thực thi trực tiếp bởi máy tính (thông qua các theo tác trên vùng nhớ). Trước đây, hầu hết các trình biên dịch cũ phải dịch từ mã nguồn sang bộ mã phụ (các tệp có dang *.obj) rồi mới tạo ra tập tin thực thi. Ngày nay, hầu hết các trình biên dịch đều có khả năng dịch mã nguồn trực tiếp thành các tập tin thực thi hay thành các dạng mã khác thấp hơn, tuỳ theo yêu cầu của người lập trình.
Điểm khác nhau giữa thông dịch và biên dịch là: trình thông dịch dịch từng câu lệnh theo yêu cầu thực thi và chương trình đích vừa tạo ra sẽ không được lưu lại; trong khi đó, trình biên dịch sẽ dịch toàn bộ chương trình, cho ra chương trình đích được lưu lại trong máy tính rồi mới thực hiện chương trình.
Một chương trình máy tính có thể được thực thi bằng cách biên dịch, thông dịch, hoặc phối hợp cả hai.
Để đạt được yêu cầu về độ chính xác và tính hiệu quả, mã viết ra nhiều khi khó đọc ngay cả với chính người viết ra mã đó, chưa kể tới người khác. Chính vì lí do đó, mọi tài liệu, hướng dẫn lập trình đều khuyên nên thêm các chú giải vào mã nguồn trong quá trình viết. Các chú giải giúp người khác rất nhiều trong việc đọc hiểu mã nguồn; đối với chương trình phức tạp, chú giải là thành phần vô cùng quan trọng trong mã nguồn.
Đặc điểm của ngôn ngữ lập trình[sửa]
Mỗi ngôn ngữ lập trình có thể được xem như là một tập hợp của các chi tiết kỹ thuật chú trọng đến cú pháp, từ vựng, và ý nghĩa của ngôn ngữ.
Những chi tiết kỹ thuật này thường bao gồm:
- Dữ liệu và cấu trúc dữ liệu
- Câu lệnh và dòng điều khiển
- Các tên và các tham số
- Các cơ chế tham khảo và sự tái sử dụng
Đối với các ngôn ngữ phổ biến hoặc có lịch sử lâu dài, người ta thường tổ chức các hội thảo chuẩn hoá nhằm tạo ra và công bố các tiêu chuẩn chính thức cho ngôn ngữ đó, cũng như thảo luận về việc mở rộng, bổ sung cho các tiêu chuẩn trước đó. Ví dụ: Với ngôn ngữ C++, hội đồng tiêu chuẩn ANSI C++ và ISO C++ đã tổ chức đến 13 cuộc hội thảo để điều chỉnh và nâng cấp ngôn ngữ này. (Xem thêm Comeau.Computing). Đối với các ngôn ngữ lập trình web như JavaScript, ta có chuẩn ECMA, W3C ([1]).
Kiểu dữ liệu[sửa]
Một hệ thống đặc thù mà theo đó các dữ liệu được tổ chức sắp xếp trong một chương trình gọi là hệ thống kiểu của ngôn ngữ lập trình. Việc thiết kế và nghiên cứu các hệ thống kiểu được biết như là lý thuyết kiểu.
Nhiều ngôn ngữ định nghĩa sẵn các kiểu dữ liệu thông dụng như:
-
integer
: rất thông dụng, được dùng để biểu diễn các số nguyên. -
char
: biểu diễn các ký tự đơn lẻ. -
string
: biểu diễn chuỗi các kí tự, hay còn gọi là chuỗi, để tạo thành câu hay cụm từ.
Ví
dụ:
trong
C/C++,
kiểu
số
nguyên
thông
dụng
có
tên
là
int
và
chiếm
4
byte
trong
hầu
hết
trình
dịch
32-bit;
kiểu
chuỗi
là
một
dãy
các
char
,
với
kí
tự
NULL
(hay
'\0'
)
ở
vị
trí
chuỗi
kết
thúc
–
dãy
có
thể
dài
hơn
chuỗi
nó
lưu
trữ.
Ví
dụ:
trong
C,
ta
không
thể
dùng
phép
tính
+
trên
kiểu
dữ
liệu
string
(tức
là
char
*
hay
char
[]
).
Hầu
hết
các
ngôn
ngữ
có
kiểu
tĩnh
thông
dụng
như
C,
C++,
Java,
D,
Delphi,
và
C#
đều
đòi
hỏi
người
lập
trình
kê
khai
rõ
ràng
kiểu
của
dữ
liệu.
Những
người
ủng
hộ
việc
này
cho
rằng
nó
sẽ
giúp
ngôn
ngữ
rõ
ràng
hơn.
Các ngôn ngữ có kiểu tĩnh lại được chia ra thành hai loại:
-
Ngôn
ngữ
kiểu
khai
báo,
tức
là
sự
thông
báo
của
biến
và
hàm
đều
được
khai
báo
riêng
về
kiểu
của
nó.
Ví dụ điển hình của loại này là Pascal, Java, C, hay C++. -
Còn
lại
là
ngôn
ngữ
loại
suy
đoán
kiểu.
Trong
đó
các
biến
và
hàm
có
thể
không
cần
được
khai
báo
từ
trước.
Linux BASH và PHP là hai ví dụ trong những kiểu này.
Suy đoán kiểu là một cơ chế mà ở đó các đặc tả về kiểu thường có thể bị loại bỏ hoàn toàn nếu có thể được, nhằm giúp cho trình dịch dễ dàng tự đoán các kiểu của các giá trị từ ngữ cảnh mà các giá trị đó được sử dụng. Ví dụ một biến được gán giá trị 1 thì trình dịch loại suy đoán kiểu không cần khai báo riêng rằng đó là một kiểuinteger
. Các ngôn ngữ suy đoán kiểu linh hoạt hơn trong sử dụng, đặc biệt khi chúng lắp đặt sự đa dạng hoá các tham số. Ví dụ của ngôn ngữ loại này là Haskell, MUMPS và ML.
Ví dụ của các ngôn ngữ này là Objective-C, Lisp, JavaScript, Tcl, Prolog, Python và Ruby.
ADA, Java, ML và Oberon là các ví dụ của ngôn ngữ có kiểu mạnh.
C, ASM, C++, Tcl và Lua là các ví dụ của ngôn ngữ có kiểu yếu.
Lưu ý:
- Các khái niệm về kiểu mạnh hay yếu có tính tương đối. Java là ngôn ngữ có kiểu mạnh đối với C nhưng yếu đối với ML. Tùy theo cách nhìn mà các khái niệm đó được dùng, nó tương tự như việc xem ngôn ngữ ASM là ở cấp thấp hơn ngôn ngữ C; trong khi Java lại là ngôn ngữ ở mức cao hơn C.
- Hai khái niệm tĩnh và mạnh cũng không đối lập nhau. Java là ngôn ngữ có kiểu mạnh và tĩnh. C là ngôn ngữ có kiểu yếu và tĩnh. Trong khi đó, Python là ngôn ngữ có kiểu mạnh và động. Tcl lại là ngôn ngữ có kiểu yếu và động. Cũng nên biết trước rằng có nhiều người đã dùng sai các khái niệm trên và cho rằng kiểu mạnh là kiểu tĩnh cộng với mạnh. Lầm lẫn hơn, họ còn cho rằng ngôn ngữ C có kiểu mạnh mặc dù rằng C không hề bắt nhiều loại lỗi về việc dùng sai kiểu.
Cấu trúc dữ liệu[sửa]
Hầu hết các ngôn ngữ đều cung cấp các cách thức để lắp ráp các cấu trúc dữ liệu phức tạp từ các kiểu sẵn có và để liên kết các tên với các kiểu mới kết hợp (dùng các kiểu mảng, danh sách, hàng đợi, ngăn xếp hay tập tin).
Các ngôn ngữ hướng đối tượng cho phép lập trình viên định nghĩa các kiểu dữ liệu mới gọi là đối tượng. trong nội bộ các đối tượng đó có riêng các hàm và các biến (và thường được gọi theo thứ tự là các phương thức và các thuộc tính). Một chương trình có định nghĩa các đối tượng sẽ cho phép các đối tượng đó thực thi như là các chương trình con độc lập nhưng lại tương tác nhau. Các tương tác này có thể được thiết kế trong lúc viết mã để mô hình hóa và mô phỏng theo đời sống thật của các đối tượng. Nói một cách đơn giản, các ngôn ngữ hướng đối tượng đã được cho thêm sức sống để có riêng những tính năng hoạt động và tương tác với thế giới bên ngoài. Ngoài ra, các đối tượng còn có thêm các đặc tính như là thừa kế và đa hình. Điều này là một ưu thế trong việc dùng ngôn ngữ loại này để mô tả các đối tượng của thế giới thực.
Các mệnh lệnh và dòng điều khiển[sửa]
Khi dữ liệu đã được định rõ, máy tính phải được chỉ thị làm thế nào để tiến hành các phép toán trên dữ liệu đó. Những mệnh đề cơ bản có thể được cấu trúc thông qua việc sử dụng các từ khóa (đã được định nghĩa bởi ngôn ngữ lập trình) hoặc là có thể tạo thành từ việc dùng và kết hợp các cấu trúc ngữ pháp hay cú pháp đã được định nghĩa. Những mệnh đề cơ bản này gọi là các câu lệnh.
Tùy theo ngôn ngữ, các câu lệnh có thể được kết hợp với nhau theo trật tự nào đó. Điều này cho phép thiết lập được các chương trình thực hiện được nhiều chức năng. Xa hơn, ngoài các câu lệnh để thay đổi và điều chỉnh dữ liệu, còn có những kiểu câu lệnh dùng để điều khiển dòng xử lý của máy tính như là phân nhánh, định nghĩa bởi nhiều trường hợp, vòng lặp, hay kết hợp các chức năng. Đây là các thành tố không thể thiếu của một ngôn ngữ lập trình.
Các tên và các tham số[sửa]
Muốn cho chương trình thi hành được thì phải có phương pháp xác định được các vùng trống của bộ nhớ để làm kho chứa dữ liệu. Phương pháp được biết nhiều nhất là thông qua tên của các biến. Tùy theo ngôn ngữ, các vùng trống gián tiếp có thể bao gồm các tham chiếu, mà thật ra, chúng là các con trỏ (pointer) chỉ đến những vùng chứa khác của bộ nhớ, được cài đặt trong các biến hay nhóm các biến. Phương pháp này gọi là đặt tên kho nhớ. Tương tự với phương pháp đặt tên kho nhớ, là phương pháp đặt tên những nhóm của các chỉ thị. Trong hầu hết các ngôn ngữ lập trình, đều có cho phép gọi đến các macro hay các chương trình con như là các câu lệnh để thi hành nội dung mô tả trong các macro hay chương trình con này thông qua tên. Việc dùng tên như thế này cho phép các chương trình đạt tới một sự linh hoạt cao và có giá trị lớn trong việc tái sử dụng mã nguồn (vì người viết mã không cần phải lặp lại những đoạn mã giống nhau mà chỉ việc định nghĩa các macro hay các chương trình con.)
Các tham chiếu gián tiếp đến các chương trình khả dụng hay các bộ phận dữ liệu đã được xác định từ trước cho phép nhiều ngôn ngữ định hướng ứng dụng tích hợp được các thao tác khác nhau.
Cơ chế tham khảo và việc tái sử dụng mã nguồn[sửa]
Mỗi ngôn ngữ lập trình đều có một bộ các cú pháp quy định việc lập trình sao cho mã nguồn được thực thi. Theo đó, mỗi nhà sản xuất ngôn ngữ lập trình sẽ cung cấp một bộ các cấu trúc ngữ pháp cho các câu lệnh, một khối lượng lớn các từ vựng quy ước được định nghĩa từ trước, và một số lượng các thủ tục hay hàm cơ bản. Ngoài ra, để giúp lập trình viên dễ dàng sử dụng, nhà sản xuất còn phải cung cấp các tài liệu tra cứu về đặc tính của ngôn ngữ mà họ phát hành. Những tài liệu tra cứu này bao gồm hầu hết các đặc tả, tính chất, các tên (hay từ khoá) mặc định, phương pháp sử dụng, và nhiều khi là các mã nguồn để làm ví dụ. Do sự không thống nhất trong các ý kiến về việc thiết kế và sử dụng từng ngôn ngữ nên có thể xảy ra trường hợp mã nguồn của cùng một ngôn ngữ chạy được cho phần mềm dịch này nhưng không tương thích được với phần mềm dịch khác. Ví dụ là các mã nguồn C viết cho Microsoft C (phiên bản 6.0) có thể không chạy được khi dùng trình dịch Borland (phiên bản 4.5) nếu không biết cách thức điều chỉnh. Đây cũng là nguyên do của các kỳ hội nghị chuẩn hóa ngôn ngữ lập trình. Ngoài công việc chính là phát triển ngôn ngữ đặc thù, hội nghị còn tìm cách thống nhất hóa ngôn ngữ bằng cách đưa ra các tiêu chuẩn, các khuyến cáo thay đổi về ngôn ngữ trong tương lai hay các đổi mới về cú pháp của ngôn ngữ.
Những đổi mới về tiêu chuẩn của một ngôn ngữ mặt khác lại có thể gây ra các hiệu ứng phụ. Đó là việc mã nguồn của một ngôn ngữ dùng trong phiên bản cũ không tương thích được với phần mềm dịch dùng tiêu chuẩn mới hơn. Đây cũng là một việc cần lưu tâm cho những người lập trình. Trường hợp điển hình nhất là việc thay đổi phiên bản về ngôn ngữ Visual Basic của Microsoft. Các mã nguồn của phiên bản 6.0 có thể sẽ không dịch được nếu dùng phiên bản mới hơn. Lý do là nhà thiết kế đã thay đổi kiến trúc của VisualBasic để nâng cao và cung cấp thêm các chức năng mới về lập trình theo định hướng đối tượng cho ngôn ngữ này.
Thay vào việc tái sử dụng mã nguồn thì cũng có các hướng phát triển khác nhằm tiết kiệm công sức cho người lập trình mà hai hướng chính là:
- Việc ra đời của các bytecode mà điển hình là ngôn ngữ Java. Với Java thì mã nguồn sẽ được dịch thành một ngôn ngữ trung gian khác gọi là bytecode. Mã của bytecode một lần nữa sẽ được phần mềm thông dịch thực thi, phần mềm này gọi là máy ảo. Các máy ảo được cài đặt sẵn trên các máy tính và được cung cấp miễn phí. Tùy theo hệ điều hành mà có thể cài đặt máy ảo thích hợp. Do đó, cùng một nguồn Java bytecode có thể chạy trong bất cứ hệ điều hành nào miễn là hệ điều hành đó có cài đặt sẵn máy ảo Java. Việc này tiết kiệm rất nhiều công sức cho lập trình viên vì họ không phải viết mã Java khác nhau cho mỗi hệ điều hành.
- Tận dụng tính chất thừa kế của các lớp (class) trong các ngôn ngữ hướng đối tượng. Theo kiểu thiết kế này, một đối tượng có thể thụ hưởng các đặc tính mà các thế hệ trước của chúng đã có. Do đó, khi phát triển phần mềm mới theo cấu trúc của các lớp, người ta chỉ cần tạo thêm các lớp con (subclass) có nhiều tính năng mới hơn. Điều này giúp giảm bớt công sức vì không phải phát triển lại từ đầu. (Lưu ý: Java cũng là một loại ngôn ngữ hướng đối tượng nên nó có luôn ưu thế này.)
Triết lý của các thiết kế[sửa]
Tùy theo mục đích của ngôn ngữ mà chúng được thiết kế để tạo điều kiện giải quyết những vấn đề mà ngôn ngữ đó hướng tới. Những chức năng này làm cho một ngôn ngữ có thể tiện lợi để dùng phát triển loại phần mềm này nhưng có thể khó để phát triển loại phần mềm khác.
Hầu hết các ngôn ngữ đòi hỏi sự chính xác cao về mặt cú pháp. Các ngôn ngữ không cho phép có lỗi. Mặc dù vậy, một số ít ngôn ngữ cũng cho phép tự điều chỉnh trong một mức độ khá cao, khi đó chương trình tự viết lại để xử lý những trường hợp mới. Các ngôn ngữ như Prolog, PostScript và các thành viên trong họ ngôn ngữ Lisp có khả năng này. Trong ngôn ngữ MUMPS, kỹ thuật này gọi là tái biên dịch động. Các phần mềm mô phỏng và nhiều máy ảo (virtual machine) khai thác kỹ thuật này để có hiệu suất cao.
Một yếu tố liên quan đến triết lý thiết kế là có một số ngôn ngữ vì muốn tạo sự dễ dàng cho người mới dùng, đã không phân biệt việc viết chữ hoa hay không. Pascal và Basic là hai ngôn ngữ không phân biệt việc một kí tự có viết hoa hay không, trái lại trong C/C++, Java, PHP, Perl, BASH đều bắt buộc phải bảo đảm việc viết đúng y hệt như lúc khai báo cho các tên.
Các thành tố căn bản của một ngôn ngữ[sửa]
Các dạng câu lệnh[sửa]
Câu lệnh là một thành tố quan trọng nhất của mọi ngôn ngữ lập trình. Tùy theo ngôn ngữ các câu lệnh đều phải tuân theo các trật tự sắp xếp của các từ khóa, tham số, biến và các định danh khác như các macro, hàm, thủ tục cũng như các quy ước khác. Tập hợp trật tự và quy tắc đó tạo thành cú pháp của ngôn ngữ lập trình. Các dạng câu lệnh bao gồm
- Định nghĩa: Dạng câu lệnh này cho phép xác định một kiểu dữ liệu mới hay một hằng. Lưu ý là trong các ngôn ngữ lập trình định hướng đối tượng thì mỗi lớp đều có thể là một kiểu dữ liệu mới do đó việc tạo ra một lớp mới tức là đã dùng câu lệnh kiểu định nghĩa.
-
Ví
dụ:
Trong
C
hay
C++,
câu
lệnh
#define PI 3.1415927
sẽ cho phép định nghĩa tên (macro) PI với giá trị không đổi là 3,1415927.
-
Khai báo: Cũng gần giống như dạng định nghĩa, dạng khai báo cho phép người lập trình chính thức thông báo về sự ra đời của một biến, hay một tên (tên hàm chẳng hạn). Thông thường, đối với ngôn ngữ tĩnh, tên hàm hay biến mới đều phải có phần cho biết kiểu dữ liệu của biến hay hàm. Tuy nhiên, điều này không bắt buộc với ngôn ngữ động. Ngoài ra, các khai báo đôi khi còn cho phép các biến gán một giá trị ban đầu nhưng thường thì việc này cũng không bắt buộc. (Xem thêm loại câu lệnh gán giá trị). Đối với nhiều ngôn ngữ thì việc khai báo có thể cho phép chương trình đó được cấp thêm một phần bộ nhớ dự trữ riêng cho các biến (hay các đối tượng) đăng ký tên trong câu lệnh khai báo.
-
Ví
dụ:
-
Trong
Java
hay
C/C++,
câu
lệnh
int line_number = 0;
thuộc loại khai báo -
Trong
Perl
hay
PHP,
câu
lệnh
$my_var;
thuộc loại khai báo
-
Trong
Java
hay
C/C++,
câu
lệnh
-
Gán giá trị là loại câu lệnh cho phép viết giá trị cụ thể vào các biến. Có thể có các giới hạn khác nhau trong việc gán giá trị này (chẳng hạn như phải tương thích về kiểu dữ liệu hay trường hợp nếu biến có các kiểu đặc biệt thì phải dùng đến các hàm hay các thủ tục để gán giá trị cho chúng).
-
Ví
dụ:
-
Trong
ASM,
câu
lệnh
mov AX, 21h
sẽ gán giá trị 21h lên thanh AX -
Trong
Java
hay
C/C++,
câu
lệnh
i = j;
sẽ gán giá trị đang có của biến j cho biến i
-
Trong
ASM,
câu
lệnh
-
Kết hợp: Hầu hết các ngôn ngữ đều cho phép thiết lập câu lệnh mới từ nhiều câu lệnh. Lưu ý: Cần dựa theo cú pháp của từng ngôn ngữ để làm việc này.
-
Ví
dụ:Trong
văn
lệnh
BASH
hai
câu
lệnh
xóa
các
tệp
có
đuôi
txt
rm -f *.txt
và câu lệnhmkdir newfolder
tạo một thư mục trống có tên 'newfolder' có thể được ghép nhau thành dãy câu có dạngrm -f *.txt; mkdir newfolder
. Thứ tự thực hiện các câu lệnh thành phần sẽ đi từ trái sang phải.
-
Điều kiện: Loại câu lệnh này dùng để chẻ nhánh dòng điều khiển của ngôn ngữ. Thường từ khóa hay được dùng nhất là
"if", "else", và "else if"
. Ngoài ra, một số ngôn ngữ có thể dùng thêm dạng câu lệnh phân nhánh đặc biệt cho trường hợp có nhiều phân nhánh (thường từ khóa bắt đầu câu lệnh điều kiện kiểu này có thể là"switch" hay là "case"
.)
-
Ví
dụ:
Trong
Java
hay
C/C++,
câu
lệnh
-
if (x==1) { y = x; }
-
else { y = x + 3; }
- là loại câu lệnh điều kiện
-
-
Vòng lặp: Dùng để lặp lại các câu lệnh giống nhau cho các đối tưọng hay các biến trong một số hữu hạn lần. Từ khóa thường gặp nhất trong các ngôn ngữ là
"for" và "while".
-
Ví
dụ:
Trong
Java
hay
C/C++,
câu
lệnh
-
for (int n=1; n!=5; ++n) { value *= n }
-
sẽ
lần
lượt
tính
giá
trị
value = value * n
làm 4 lần với các giá trị của biến n lần lượt là 1,2,3,4. Giá trị sau cùng nhận về của value sẽ là (value * 4!).
-
- Gọi loại lệnh này dùng để thực thi các hàm, các thủ tục, hay các macro đã được định nghĩa sẵn bởi các thư viện hay bởi người lập trình.
-
Ví
dụ:
Trong
C/C++,
câu
lệnh
printf("Hello, world!\n");
- gọi hàm cho sẵn nhằm hiển thị dòng chữ
-
"
Hello, world!
<dấu xuống hàng>"
-
Các định hướng dịch hay còn gọi là các chỉ thị tiền xử lý: Ngoài các thành tố trên, các nhà sản xuất các phần mềm dịch (đặc biệt là các trình dịch) còn có thể cung cấp thêm các dạng câu lệnh không trực tiếp tham gia vào việc tính toán trên các dữ liệu của chương trình nhưng lại trực tiếp điều khiển các dòng chuyển dịch mã ở thời điểm dịch cũng như là hướng dẫn các trình dịch cách xử lý, tìm nguồn mã bổ sung, cách dùng thư viện, hay các cài đặt đặc biệt cho một loại hệ điều hành hay cho một loại phần cứng nào đó. Các câu lệnh này có thể tùy thuộc vào nhà sản xuất phần mềm chuyển dịch cung cấp.
-
Ví
dụ:
Trong
C/C++
các
câu
lệnh
-
#ifndef MY_LIB
-
#include "my_code.h"
-
#endif
- sẽ kiểm tra nếu tên MY_LIB chưa được định nghĩa trước đây trong chương trình thì sẽ tiếp tục đọc tệp my_code.h (để nhận vào các định nghĩa, hay các khai báo có trong tệp my_code.h rồi tiếp tục dịch mã.)
-
-
Chú giải Các câu lệnh loại này không tham gia vào bất kỳ hoạt động nào trong quá trình dịch nghĩa là các phần mềm dịch sẽ bỏ qua các dòng này. Tuy nhiên, các câu lệnh loại chú giải có giá trị văn bản. Người ta thường dùng chúng để ghi chú các kỹ thuật, các tính năng hay những điều cần nhớ để sau này khi đọc lại mã nguồn thì có thể hiểu được người lập trình đã làm gì.
-
Thí
du:
Trong
Java,
C/C++,
PHP
các
câu
chú
giải
có
thể
bắt
đầu
bởi
dấu
"//"
-
//hàm "SUM(n,r,m)" dùng để tính tổng số tiền có được khi gửi ngân hàng
-
// n=số tháng, r = lãi suất trong năm, m = vốn gửi ban đầu
- sẽ là hai câu lệnh chú giải.
-
Lưu ý: để hiểu rõ hơn và sử dụng thuần thục các dạng câu lệnh thì người lập trình nên tham khảo các tài liệu giảng giải riêng về từng ngôn ngữ.
Chương trình con và macro[sửa]
- Một chương trình con (còn được gọi là hàm, thủ tục, hay thủ tục con) là một chuỗi mã để thực thi một thao tác đặc thù nào đó như là một phần của chương trình lớn hơn. Đây là các câu lệnh được nhóm vào một khối và được đặt tên và tên này tùy theo ngôn ngữ có thể được gán cho một kiểu dữ liệu. Những khối mã này có thể được tập trung lại làm thành các thư viện phần mềm. Các chương trình con có thể được gọi ra để thi hành (thường là qua tên của chương trình con đó). Điều này cho phép các chương trình dùng tới những chương trình con nhiều lần mà không cần phải lặp lại các khối mã giống nhau một khi đã hoàn tất việc viết mã cho các chương trình con đó chỉ một lần.
Trong một số ngôn ngữ, người ta lại phân biệt thành 2 kiểu chương trình con:
-
Hàm (function) dùng để chỉ các chương trình con nào có giá trị trả về (trong một kiểu dữ liệu nào đó) thông qua tên của hàm.
-
Thủ tục (subroutine) dùng để mô tả các chương trình con được thi hành và không có giá trị trả về.
Tuy
nhiên,
trong
nhiều
ngôn
ngữ
khác
như
C
chẳng
hạn
thì
không
có
sự
phân
biệt
này
và
chỉ
có
một
khái
niệm
hàm.
Để
mô
tả
các
hàm
không
trả
về
giá
trị
(tương
đương
với
khái
niệm
thủ
tục)
thì
người
ta
có
thể
gán
cho
kiểu
dữ
liệu
của
hàm
đó
là
void
.
Lưu ý: trong các ngôn ngữ hướng đối tượng, mỗi một đối tượng hay một thực thể (instance), tùy theo quan điểm, có thể được xem là một chương trình con hay một biến vì bản thân nội tại của thực thể đó có chứa các phương thức và cả các dữ liệu có thể trả lời cho các lệnh gọi từ bên ngoài.
- macro được hiểu là tên viết tắt của một tập các câu lệnh. Như vậy, trong những chương trình có các khối câu lệnh giống nhau thì người ta có thể định nghĩa một macro cho khối đại diện và có thể dùng tên của macro này trong lúc viết mã thay vì phải viết cả khối câu lệnh mỗi lần khối này xuất hiện lặp lại. Một cách trừu tượng, thì macro là sự thay thế một dạng thức văn bản xác định bằng việc định nghĩa của một (hay một bộ) quy tắc. Trong quá trình dịch, các phần mềm dịch sẽ tự động thay các macro này trở lại bằng các mã mà nó viết tắt cho, rồi mới tiếp tục dịch. Như vậy, các mã này được điền trả lại trong thời gian dịch. Một số ngôn ngữ có thể cho các macro được phép khai báo và sử dụng tham số. Như vậy về vai trò macro giống hệt như các chương trình con.
Các điểm khác nhau quan trọng giữa một chương trình con và một macro bao gồm:
-
Mã
của
chương
trình
con
vẫn
được
dịch
và
để
riêng
ra.
Cho
tới
khi
một
chương
trình
con
được
gọi
ở
thời
điểm
thi
hành,
thì
các
mã
đã
dịch
sẵn
của
chương
trình
con
này
mới
được
lắp
vào
dòng
chạy
của
chương
trình.
Trong khi đó, sau khi dịch, các macro sẽ không còn tồn tại. Trong chương trình đã được dịch, tại các vị trí có tên của macro thì các tên này được thay thế bằng khối mã (đã dịch) mà nó đại diện. - Cách viết mã dùng chương trình con sau khi dịch xong sẽ tạo thành các tập tin ngắn hơn so với cách viết dùng macro.
- Ngược lại khi máy tính tải lên thì một phần mềm có cách dùng macro ít tốn tính toán của CPU hơn là phần mềm đó phát triển bằng phương pháp gọi các chương trình con.
Biến, hằng, tham số, và đối số[sửa]
-
Một
biến
(variable)
là
một
tên
biểu
thị
cho
một
số
lượng,
một
ký
hiệu
hay
một
đối
tượng.
Thêm
vào
đó,
một
biến
sẽ
được
dành
sẵn
chỗ
(phần
của
bộ
nhớ)
để
chứa
số
lượng,
ký
hiệu
hay
đối
tượng
đó.
Trong
lúc
chương
trình
được
thi
hành
thì
các
biến
của
chương
trình
sẽ
có
thể
thay
đổi
giá
trị
hoặc
không
thay
đổi
gì
cả.
Hơn
nữa,
một
biến
có
thể
bị
thay
đổi
cả
lượng
bộ
nhớ
mà
nó
đang
chiếm
hữu
(do
người
lập
trình
hay
do
phần
mềm
dịch
ra
lệnh).
Trường
hợp
biến
này
không
được
gán
giá
trị
hay
có
gán
giá
trị
nhưng
không
được
sử
dụng
vào
các
tính
toán
thì
nó
chỉ
chiếm
chỗ
trong
bộ
nhớ
một
cách
vô
ích.
Mỗi
biến
sẽ
có
tên
của
nó
và
có
thể
có
kiểu
xác
định.
Tùy
theo
ngôn
ngữ,
một
biến
có
thể
được
khai
báo
ở
vị
trí
nào
đó
trong
mã
nguồn
và
cũng
tùy
ngôn
ngữ,
tùy
phần
mềm
dịch
và
cách
thức
lập
trình
mà
một
biến
có
thể
được
tạo
nên
(cùng
với
chỗ
chứa)
hay
bị
xóa
bỏ
tại
một
thời
điểm
nào
đó
trong
lúc
thực
thi
chương
trình.
Việc
các
biến
bị
xóa
bỏ
là
để
tiết
kiệm
bộ
nhớ
cũng
như
làm
tốt
hơn
việc
quản
lý
phần
bộ
nhớ
mà
đôi
khi
một
chương
trình
chỉ
được
cấp
bởi
đăng
ký
với
hệ
điều
hành.
Quá trình tồn tại của một biến gọi là đời sống của biến. Trong nhiều trường hợp đời sống của một biến chỉ xảy ra trong nội bộ một hàm, một thủ tục hay trong một khối mã.
- Một hằng (constant) là một giá trị số hay ký hiệu được gán cho một tên xác định. Khác với biến, hằng không bao giờ thay đổi giá trị. Vì lý do tiện lợi trong việc viết mã, thường đời sống của một hằng lâu dài hơn một biến và có khi nó tồn tại trong suốt toàn bộ thời gian thi hành của chương trình. Trong nhiều trường hợp hằng có thể được xác định kiểu hay không. (C++ là ngôn ngữ cho phép có cả hai cách định nghĩa hằng có kiểu hay không có kiểu và câu lệnh để tạo ra hai loại này là hoàn toàn khác nhau). Nếu một biến hoàn toàn không thay đổi giá trị của nó trong mọi tình huống thì vai trò của biến này tương đương với một hằng.
- Khác với biến, tham số (parameter) cũng là các tên được các chương trình con hay macro dùng để tính toán. Khi được gọi thì chương trình con, hay macro sẽ đòi hỏi các tên này phải được gán giá trị cụ thể trước khi tiến hành tính toán.
- Các giá trị được gán lên cho các tham số để một chương trình con hay macro thi hành gọi là các đối số (argument). Một cách đơn giản, các đối số là các giá trị thông tin hay dữ liệu cung cấp cho các chương trình con hay macro trước khi tính toán.
Các tham số giống biến ở chỗ chúng thường có kiểu xác định. Bên trong chương trình con, hay macro, các tham số thường đóng vai trò của hằng nhưng trong nhiều trường hợp khác chúng vẫn có thể hoạt động như các biến và điều này cũng phụ thuộc vào các đặc tính của mỗi ngôn ngữ.
Nếu nhìn toàn bộ chương trình như một hàm lớn thì tham số của hàm này gọi là tham số của chương trình và các tham số của chương trình này có thể tương tác với các chương trình khác và ngược lại. Một cách đơn giản thì tham số là các dữ liệu truyền đi giữa các chương trình hay các hàm, thủ tục hay macro.
Từ vựng quy ước[sửa]
Từ
vựng
quy
ước
là
những
dãy
các
kí
tự
hay
kí
hiệu
(thường
tạo
thành
các
chữ
có
ý
nghĩa)
nối
nhau
và
được
một
ngôn
ngữ
cho
sử
dụng
như
là
tên,
giá
trị
hay
một
luật
nào
đó.
Người
viết
mã
nên
tránh
sử
dụng
các
từ
quy
ước
này
vào
việc
đặt
tên
(cho
các
biến,
hàm,
hay
các
đối
tượng
khác)
để
tránh
không
gây
ra
các
lỗi
dạng
ambiguity
(nghĩa
là
từ
dùng
có
nhiều
nghĩa
khiến
cho
phần
mềm
dịch
không
biết
phải
chọn
cách
nào).
Tuy
nhiên,
tuỳ
theo
từng
trường
hợp
mà
một
tên
mới
đặt
ra
trùng
với
các
tên
đã
quy
định
có
được
chấp
nhận
hay
không
và
việc
chấp
nhận
này
sẽ
có
hiệu
ứng
phụ
gì.
Thí
dụ
-
Trong
C
thì
việc
viết
#define MYVALUE 10;
thì dãy kí tự "#define" sẽ là một từ vựng quy ước (thuộc về câu lệnh dạng định nghĩa) -
Trong
C/C++
nếu
dùng
từ
int
để khai báo như là tên của một biến chẳng hạn nhưunsigned int;
thì lập tức khai báo này sẽ bị trình dịch bắt lỗi.
Từ khóa[sửa]
Từ
khóa
trong
ngôn
ngữ
lập
trình
là
các
từ
hay
ký
hiệu
mà
đã
được
ngôn
ngữ
đó
gán
cho
một
ý
nghĩa
xác
định.
Người
lập
trình
sẽ
không
được
phép
dùng
lại
các
từ
khóa
này
dưới
một
ý
nghĩa
khác.
Thường
các
từ
khóa
này
được
ngôn
ngữ
xác
định
dùng
trong
các
kiểu
dữ
liệu
cơ
bản
hay
trong
các
dòng
điều
khiển.
Ví
dụ
một
số
từ
khóa
trong
C
và
C++:
auto,
float,
return,
char,
if
else,
static,
void...
Các tên chuẩn hay tên cho trước[sửa]
Ngoài các từ khóa, một ngôn ngữ lập trình còn có khối lượng khá lớn các tên đã được định nghĩa hay được gán cho các ý nghĩa chuyên biệt gọi là các tên chuẩn. Các tên này có thể được dùng lại cho một ý nghĩa khác tùy theo người viết mã. Trong nhiều trường hợp sẽ phải có một cơ chế gọi để phân biệt là người lập trình muốn ám chỉ các tên đã bị tái dụng này dưới ý nghĩa nguyên thủy hay dưới ý nghĩa mới. Thường các tên được phép định nghĩa lại nằm trong hai loại chính là:
- Các hàm hay thủ tục chuẩn.
- Các biến toàn cục (global)
Ví dụ
-
Trong
C
thì
sin
là tên của một hàm tính giá trị sin (trong thư viện math.h) nhưng người lập trình hoàn toàn có thể định nghĩa lại hàm này để cho nó có chức năng khác. -
Trong
văn
lệnh
BASH
thì
biến
toàn
cục
$PATH
có thể được định nghĩa lại để dùng như là một biến địa phương.
Các kí hiệu[sửa]
Trong mỗi ngôn ngữ đều cung cấp một hệ thống ký hiệu hay ký tự có ý nghĩa riêng. Tùy theo ngôn ngữ mà các ký hiệu này được phép định nghĩa lại hay không. Những ký hiệu được đùng trong hai trường hợp thường thấy nhất là
- Dùng để chỉ các phép toán.
- Dùng trong cú pháp. Trường hợp này thì các ký hiệu này giữ vai trò tương tự như các dấu chấm câu trong các ngôn ngữ tự nhiên.
Ví dụ:
-
Trong
C/C++/Java/PHP
thì
các
dấu
kí
hiệu
'+', '-', '*', '/', '='
được dùng trong các phép toán theo thứ tự là cộng, trừ, nhân, chia và phép toán gán giá trị. -
Trong
C
thì
các
dấu
'+', '-', '*', '/',...
là không thể dùng lại cho ý nghĩa khác. Trong khi đó nếu dùng C++ thì người lập trình hoàn toàn có khả năng định nghĩa chúng lại thành những phép toán mới theo ý riêng và áp dụng cho các đối tượng mà người lập trình mong muốn (chẳng hạn như dùng phương pháp "quá tải toán tử"). -
Trong
C,
C++,
PHP,
Perl,
Java
và
Pascal
thì
kết
thúc
các
câu
lệnh
đơn
giản
thường
bắt
buộc
phải
dùng
dấu
';'
. Và điều này thì không nhất thiết nếu dùng văn lệnh BASH. Dấu ';' này giữ vai trò tương tự như dấu '.' trong Việt ngữ hay Anh ngữ. (Có điều là đại đa số các ngôn ngữ lập trình sẽ tuyệt đối không cho phép việc viết sai cú pháp.)
Các luật cấm và ngoại lệ[sửa]
Mỗi ngôn ngữ, do hạn chế của môi trường và bản thân ngôn ngữ cũng như do mục tiêu sử dụng, có thể có một số luật cấm mà người lập trình không thể vi phạm. Những luật cấm này có thể có những cách xử lý khác nhau như là:
- Nhiều ngôn ngữ cho phép dùng các câu lệnh đặc biệt để lập trình viên có toàn quyền xử lý lỗi và thường được gọi là ngoại lệ (hay exception). Những ngoại lệ này nếu không xử lý đúng mức sẽ có thể gây ra những sai sót trong thời gian thi hành hay ngay cả trong thời gian dịch. Dĩ nhiên, người viết mã có thể tùy theo tình huống mà viết các câu lệnh rẽ nhánh tránh không để cho mã vi phạm các lỗi. Hay là dùng các câu lệnh xử lý các ngoại lệ này.
- Một số ngôn ngữ không cung cấp khả năng xử lý ngoại lệ thì người viết mã buộc phải tự mình phán đoán hết các tình huống có thể vi phạm lỗi và dùng câu lệnh điều kiện để loại trừ.
Các loại lỗi về ngôn ngữ khi lập trình thường xảy ra là
Lỗi cú pháp[sửa]
- Vi phạm khi đặt hay gọi tên biến và hàm: Lỗi loại này thường rất dễ tìm ra trong lúc phát triển mã. Thường người ta có thể đọc lại các bảng tham chiếu về ngôn ngữ để tránh sai cú pháp mẫu (prototype) của hàm hay tránh dùng các ký tự đặc biệt bị cấm không cho dùng trong khi đặt tên. Trong không ít trường hợp người lập trình có thể đã định nghĩa cùng một tên cho nhiều hơn một đối tượng khác nhau và lại có giá trị toàn cục. Trong nhiều trường hợp chúng tạo thành lỗi ý nghĩa.
- Lỗi chính tả: người viết mã có thể viết hay gọi sai tên hàm, tên biến. Trong nhiều ngôn ngữ có kiểu tĩnh thì các lỗi này sẽ rất dễ bị phát hiện. Còn đối với ngôn ngữ có kiểu động hay có kiểu yếu thì nó có thể dẫn đến sai sót nghiêm trọng vì bản thân phần mềm dịch không hề phát hiện ra.
-
Vượt
quá
khả
năng
tính
toán:
Bản
thân
máy
tính
và
hệ
điều
hành
cũng
có
rất
nhiều
giới
hạn
về
phần
cứng,
phần
mềm
và
các
đặc
điểm
chuyên
biệt.
Khi
người
lập
trình
yêu
cầu
máy
làm
quá
khả
năng
sẽ
gây
ra
các
lỗi
mà
đôi
khi
không
xác
định
được
như
- Lỗi thời gian (timing error) thường thấy trong các hệ thống đa luồng hay đa nhiệm.
- Lỗi chia cho 0: Bản thân phần cứng máy tính sẽ ở trạng thái bất định khi thực hiện phép chia cho 0; trong nhiều trường hợp, mã sau khi dịch mới phát hiện ra trong lúc thi hành và được đặt tên là lỗi division by 0.
- Dùng hay gọi tới các địa chỉ hay các thiết bị mà bản thân máy hay hệ điều hành đang thực thi lại không có hay không thể đạt tới. Đây là trường hợp rất khó lường. Bởi vì thường ngưòi lập trình có thể viết mã trên một máy nhưng lại cho thi hành trong các máy khác và các máy này lại không thỏa mãn các yêu cầu. Để giảm trừ các lỗi loại này thường người lập trình nên xác định trước các điều kiện mà phần mềm làm ra sẽ hỗ trợ.
-
- Ví dụ: trong nhiều phần mềm ngày nay ở trong vỏ hộp đều được ghi rõ các yêu cầu về vận tốc, bộ nhớ tối thiểu, và quan trọng là hệ điều hành nào mà phần mềm đó hỗ trợ.
- Gán sai dữ liệu: Tức là dùng một dữ liệu có kiểu khác với kiểu của biến để gán cho biến đó một cách không chủ ý. Đối với các ngôn ngữ tĩnh hay có kiểu mạnh thì lỗi này dễ tìm thấy hơn. Còn những ngôn ngữ động hay ngôn ngữ có kiểu yếu thì lỗi tạo ra sẽ có thể khó phát hiện và thường xảy ra lúc thi hành.
-
Các
lỗi
biên:
Lỗi
biên
thường
xảy
ra
khi
người
viết
mã
không
chú
ý
đến
các
giá
trị
ở
biên
của
các
biến,
các
hàm.
Những
lỗi
để
thấy
có
thể
là:
-
Gán
giá
trị
của
một
số
(hay
một
chuỗi)
lên
một
biến
mà
nó
vượt
ngoài
sự
cho
phép
của
định
nghĩa.
Ví dụ: Gán một giá trị lớn hơn 255 cho một biến có kiểu làshort
trong ngôn ngữ C -
Tạo
nên
các
lỗi
khi
biến
chạy
trong
vòng
lặp
đạt
giá
trị
ở
biên.
Ví dụ: đoạn mã C/C++ sau đây sẽ gây ra lỗi biên—Chia cho 0
-
Gán
giá
trị
của
một
số
(hay
một
chuỗi)
lên
một
biến
mà
nó
vượt
ngoài
sự
cho
phép
của
định
nghĩa.
-
-
for (m=10; m >= 0, m--) {
-
x= 8+ 2/m; }
-
-
Lỗi ý nghĩa[sửa]
- Lỗi về quản lý bộ nhớ. Trong nhiều loại ngôn ngữ người lập trình có thể xin đăng ký một lượng nào đó của bộ nhớ để dùng làm chỗ chứa giá trị cho một biến (một hàm hay một đối tượng). Thường thì sau khi dùng xong người viết mã phải có phần lệnh trả về các phần bộ nhớ mà nó đã đăng ký dùng. Nếu không, sự trả về này chỉ xảy ra ở giai đoạn kết thúc việc thi hành. Trong nhiều trường hợp, số lượng bộ nhớ xin đăng ký quá nhiều và không được dùng đúng chỗ có thể làm cho máy kiệt quệ về mặt tài nguyên bộ nhớ và gây ra treo máy. Điển hình nhất là việc xin đăng ký các phần của bộ nhớ trong các vòng lặp lớn để gán cho các đối tượng bên trong vòng lặp nhưng không trả về sau khi sử dụng. Người ta thường gọi lỗi kiểu này là lỗi rò rỉ bộ nhớ (memory leaking).
- Sai sót trong thuật toán: Trước khi viết một chương trình, để giảm thiểu sai sót về mặt lập luận thì người ta có nhiều biện pháp để làm giảm lỗi trong đó có các phương pháp vẽ lưu đồ, vẽ sơ đồ khối, hay viết mã giả. Những biện pháp này nhằm tạo nên các thuật toán để giải quyết vấn đề. Tuy nhiên, một thuật toán không chặt chẽ, xử lý không rốt ráo mọi trường hợp có thể xảy ra, không dự đoán được sự thay đổi trong lúc thi hành thì có thể tạo nên các lỗi và các lỗi này thường khó thấy bởi vì nó chỉ xảy ra ở những chỗ, những thời điểm mà người lập trình không ngờ trước. Một trong những phương pháp đơn giản làm giảm thiểu lỗi thuật toán là phải chú ý xử lý mọi tình huống khi dùng câu lệnh điều kiện (hay chẻ nhánh) mặc dù có thể có các trường hợp tưởng như hiển nhiên.
- Lỗi về lập luận: Đây có thể xem là trường hợp đặc biệt của sai sót trong thuật toán. Trong các biểu thức tính giá trị, đôi khi không quen dùng đại số Bool (nhất là khi dùng luật De Morgan để phủ định một biểu thức phức tạp) nên người lập trình có thể tính toán sai, hay định nghĩa sai các phép toán. Do đó, giá trị trả về của các biểu thức logic hay biểu thức nhị phân sẽ bị sai trong một vài trường hợp hay toàn bộ biểu thức. Trong những tình huống như vậy phần mềm dịch sẽ không thể nào phát hiện ra cho đến khi chương trình được thi hành và lọt vào tình huống tính sai của người lập trình.
Các thành tố đặc trưng của ngôn ngữ OOP[sửa]
- Xem chi tiết: Lập trình hướng đối tượng
OOP là chữ viết tắt của Object Oriented Programming có nghĩa là Lập trình hướng đối tượng được phát minh năm 1965 bởi Ole-Johan Dahl và Kristen Nygaard trong ngôn ngữ Simula. So với phương pháp lập trình cổ điển, thì triết lý chính bên trong loại ngôn ngữ loại này là để tái dụng các khối mã nguồn và cung ứng cho các khối này một khả năng mới: chúng có thể có các hàm (gọi là các phương thức) và các dữ liệu (gọi là thuộc tính) nội tại. Khối mã như vậy được gọi là đối tượng. Các đối tượng thì độc lập với môi trường và có khả năng trả lời với yêu cầu bên ngoài tùy theo thiết kế của người lập trình. Với cách xây dựng này, mỗi đối tượng sẽ tương đương với một chương trình riêng có nhiều đặc tính mới mà quan trọng nhất là tính đa hình, tính đóng, tính trừu tượng và tính thừa kế.
Thừa kế[sửa]
Đây là đặc tính cho phép tạo các đối tượng mới từ đối tượng ban đầu và lại có thể có thêm những đặc tính riêng mà đối tượng ban đầu không có. Cơ chế này cho phép người lập trình có thể tái sử dụng mã nguồn cũ và phát triển mã nguồn mới bằng cách tạo ra các đối tượng mới thừa kế đối tượng ban đầu.
Đa hình[sửa]
Tính đa hình được thể hiện trong lập trình hướng đối tượng rất đặc biệt. Người lập trình có thể định nghĩa một thuộc tính (chẳng hạn thông qua tên của các phương thức) cho một loạt các đối tượng gần nhau nhưng khi thi hành thì dùng cùng một tên gọi mà sự thi hành của mỗi đối tượng sẽ tự động xảy ra tương ứng theo từng đối tượng không bị nhầm lẫn.
- Ví dụ: khi định nghĩa hai đối tượng "hinh_vuong" và "hinh_tron" thì có một phương thức chung là "chu_vi". Khi gọi phương thức này thì nếu đối tượng là "hinh_vuong" nó sẽ tính theo công thức khác với khi đối tượng là "hinh_tron".
Trừu tượng[sửa]
Đặc tính này cho phép xác định một đối tượng trừu tượng, nghĩa là đối tượng đó có thể có một số đặc điểm chung cho nhiều đối tượng nhưng bản thân đối tượng này có thể không có các biện pháp thi hành.
- Ví dụ: người lập trình có thể định nghĩa đối tượng "hinh" hoàn toàn trừu tượng không có đặc tính mà chỉ có các phương thức được đặt tên chẳng hạn như "chu_vi", "dien_tich". Để thực thi thì người lập trình buộc phải định nghĩa thêm các đối tượng cụ thể chẳng hạn định nghĩa "hinh_tron" và "hinh_vuông" dựa trên đối tượng "hinh" và hai định nghĩa mới này sẽ thừa kế mọi thuộc tính và phương thức của đối tượng "hinh".
Đóng[sửa]
Tính đóng ở đây dược hiểu là các dữ liệu (thuộc tính) và các hàm (phương thức) bên trong của mỗi đối tượng sẽ không cho phép người gọi dùng hay thay đổi một cách tự do mà chỉ có thể tương tác với đối tượng đó qua các phương thức được người lập trình cho phép. Tính đóng ở đây có thể so sánh với khái niệm "hộp đen", nghĩa là người ta có thể thấy các hành vi của đối tượng tùy theo yêu cầu của môi trường nhưng lại không thể biết được bộ máy bên trong thi hành ra sao.
Một số thành tố thường thấy khác của một ngôn ngữ lập trình hiện đại[sửa]
Nhiều ngôn ngữ lập trình hiện đại, nhất là các ngôn ngữ viết cho Windows, thường có cung cấp thêm một số lượng rất lớn các thư viện bao gồm nhiều hàm để hỗ trợ giao diện người dùng và các thiết bị đầu cuối.
Giao diện đồ họa[sửa]
Các ngôn ngữ chuẩn thường không đề cập tới sự cung cấp thư viện giúp cho việc thiết lập giao diện đồ họa (graphic interface). Nhưng hầu hết trong các ngôn ngữ hiện đại mà nhà sản xuất cung cấp cho các hệ điều hành đều có thêm thư viện các hàm và các biến toàn cục có thể dùng để nhanh chóng viết mã có giao diện phù hợp.
- Ví dụ như GDK (cho Linux), Java (cho mọi hệ), Visual C/C++/C# (cho Windows),... Và các thư viện này ngày nay đã trở thành các thành tố không thể thiếu cho người lập trình.
Điều khiển theo sự kiện[sửa]
Tương tự trên, triết lý đằng sau của việc điều khiển theo sự kiện là để hỗ trợ cho việc đồng bộ sử dụng cùng lúc nhiều thiết bị đầu cuối như là chuột, bàn phím, máy in... Việc nhận một mệnh lệnh từ chuột hay từ bàn phím phải được lập tức đồng bộ và thay đổi giao điện tức thời để cập nhật hoá.
Thời gian thực[sửa]
Bản thân một ngôn ngữ sẽ không nói rõ là có hỗ trợ cho tính năng này hay không. Phản ứng và cập nhật dữ liệu theo thời gian thực là một hướng phát triển nhằm đáp ứng các nhu cầu đồng bộ hoá nhanh dữ liệu mà chúng có thể chia sẻ cho nhiều nơi hay là để thỏa mãn nhu cầu cần thiết đồng bộ hóa dữ liệu của các dịch vụ (ngân hàng, hàng không và quân sự chẳng hạn).
Hỗ trợ hệ điều hành[sửa]
Ngoài các hỗ trợ cho các giao diện thì ngày nay hầu hết các hệ điều hành (Linux/UNIX, Netware và Windows) đều có khả năng đa luồng (multithreading) hay đa nhiệm (multitasking). Những khả năng này nâng cao hiệu quả của máy tính. Các ngôn ngữ, do đó thường có thêm các hàm, thủ tục hay các biến cho phép người lập trình tận dụng chúng. Việc viết mã cho kiến trúc đa luồng và đa nhiệm không đơn giản như viết mã cho các hệ thống thông thường. Người lập trình ngoài kỹ năng viết mã, còn phải luyện tập cách xử lý và đồng bộ nhiều thao tác được thi hành đồng thời trong một chương trình mà không gây ra ách tắc hay vi phạm các nguyên tắc quản lý bộ nhớ hay các quy tắc lập trình theo đa luồng hay đa nhiệm.
Lưu ý: Hầu hết các hệ điều hành hỗ trợ kiến trúc đa luồng hay đa nhiệm đều có khả năng thực thi những chương trình được tạo ra từ mã viết theo kiểu thông thường mà không đá động tới các chức năng đa luồng hay đa nhiệm. Điểm khác nhau là khi không dùng tới các ưu điểm đa luồng hay đa nhiệm thì chương trình đó sẽ không tận dụng được ưu thế phần cứng và phần mềm hỗ trợ (thường thì chương trình đó chạy chậm hơn)
Lịch sử[sửa]
- Xem chi tiết: Lịch sử các ngôn ngữ lập trình
Xem thêm[sửa]
- Phần mềm
- Assembly (Hợp ngữ)
- C
- C++
- C#
- D[5]
- Delphi
- LabVIEW
- Java
- J++
- Basic
- Pascal
- Foxpro
- Perl
- PHP
- ASP.NET
- JSP (JavaServer Pages)
- Python
- ASM
- ADA
- ICON
- Fortran
- Ruby
- SDK
- Python
- Trình dịch
- Trình biên dịch
- Trình thông dịch
- Mã lệnh
- Callback
- OOP hay lập trình hướng đối tượng
Chỉ dẫn[sửa]
Tham khảo[sửa]
- ↑ “CSC-302 99S : Class 02: A Brief History of Programming Languages”. Math.grin.edu. Truy cập Lỗi khi kêu gọi {{Chú thích web}}: hai tham số url và title phải được chỉ định..
- ↑ U.S. Census Bureau: The Hollerith Machine
- ↑ “Columbia University Computing History - Herman Hollerith”. Columbia.edu. Truy cập Lỗi khi kêu gọi {{Chú thích web}}: hai tham số url và title phải được chỉ định..
- ↑ Ritchie S. King. “The Top 10 Programming Languages”. Truy cập Lỗi khi kêu gọi {{Chú thích web}}: hai tham số url và title phải được chỉ định..
- ↑ Cade Metz (Lỗi khi kêu gọi {{Chú thích web}}: hai tham số url và title phải được chỉ định.). “The Next Big Programming Language You’ve Never Heard Of” (bằng en). Wired. Condé Nast. Truy cập Lỗi khi kêu gọi {{Chú thích web}}: hai tham số url và title phải được chỉ định..
- PC Assembly Language—Paul Morneau—West—ISBN 0-314-01003-3
- Mastering Borland C++ -- Tom Swan—SAMS—ISBN 0-672-30274-8
- Java Programer's Library—Suleiman "Sam" Lalani & Kris Jamsa—JP—ISBN 1-884133-26-6]
- New C Primer Plus—The Waite Group's -- SAms Publishing—ISBN 0-672-30319-1
- C++ How To Program—H.M. Deitel & P.J. Deitel—Prentice Hall—ISBN 0-13-117334-0
Liên kết ngoài[sửa]
Bản mẫu:Các ngôn ngữ lập trình chính Bản mẫu:Ngôn ngữ máy tính Bản mẫu:Dạng ngôn ngữ lập trình Bản mẫu:Khoa học Máy tính
Bài liên quan
Liên kết đến đây
- Bản mẫu:Switch
- Bản mẫu:If
- Thành viên:Vloser
- Lí thuyết ngôn ngữ lập trình
- Alan Turing
- Ngữ pháp
- Phương trình
- Trí tuệ nhân tạo
- Phần mềm
- Máy tính
- Xem thêm liên kết đến trang này.