Hoạt động gán
Kết quả tính toán biểu thức thường phải được lưu trữ ở đâu đó. Toán tử gán được biểu thị bằng =
được dùng cho mục đích này trong ngôn ngữ. Tên của một biến hoặc một phần tử mảng được đặt ở bên trái của nó, trong đó kết quả phải được lưu trữ, trong khi biểu thức (thực tế là công thức tính toán) nằm ở bên phải.
Chúng ta đã sử dụng toán tử này để khởi tạo biến, chỉ được thực hiện một lần trong quá trình tạo biến. Tuy nhiên, phép gán cho phép thay đổi giá trị của biến trong quá trình thuật toán với số lần tùy ý. Ví dụ:
int z;
int x = 1, y = 2;
z = x;
x = y;
y = z;
2
3
4
5
Các biến x
và y
được khởi tạo bằng giá trị 1 và 2, sau đó biến thứ ba phụ trợ z
và ba phép gán được sử dụng để trao đổi giá trị x
và y
.
Toán tử gán, giống như tất cả các toán tử khác, trả về kết quả của nó vào biểu thức. Điều này cho phép viết các phép gán theo trình tự.
int x, y, z;
x = y = z = 1;
2
Ở đây, 1 đầu tiên sẽ được gán cho biến z
, sau đó đến biến y
và cuối cùng đến biến x
. Rõ ràng, toán tử này là toán tử liên kết phải, vì giá trị được gán sẽ trôi từ phải sang trái trong biểu thức.
Chúng ta có thể sử dụng phép gán như một phần của biểu thức. Nhưng vì mức độ ưu tiên của phép gán thấp hơn các toán tử khác (trừ toán tử "dấu phẩy", hãy xem mục Mức độ ưu tiên của phép toán), nên phép gán phải được đặt trong dấu ngoặc đơn (để biết thêm chi tiết, vui lòng xem phần Nhóm với dấu ngoặc đơn). Khía cạnh này cho phép các tình huống mà các lỗi nhập, chẳng hạn như =
thay vì ==
, trong biểu thức dẫn đến việc không thực hiện các câu lệnh như mong muốn. Xem ví dụ về hành vi như vậy trong phần xử lý câu lệnh if
.
Toán tử gán áp đặt một số hạn chế nhất định đối với những gì có thể ở bên trái của =
và những gì ở bên phải của nó. Trong lập trình, các thực thể này nhằm mục đích đơn giản hóa việc lưu trữ được đặt tên chính xác là: LValue
và RValue
(dựa trên Left
và Right
).
INFO
LValue và RValue
LValue
biểu diễn một thực thể, trong đó bộ nhớ được phân bổ và do đó, có thể ghi giá trị vào đó. Các phần tử biến và mảng là các ví dụ đã biết của LValue
. Sau khi nghiên cứu OOP, chúng ta sẽ tìm hiểu một đại diện khác của loại này: Đối tượng, trong đó toán tử gán có thể được tải lại. Một phần tử bắt buộc của LValue
là sự hiện diện của một mã định danh.
Cần lưu ý rằng các biến và mảng có thể được mô tả bằng từ khóa const
, và sau đó chúng không thể hoạt động như LValue
, vì việc sửa đổi hằng số bị cấm.
RValue
là một giá trị tạm thời được sử dụng trong một biểu thức, chẳng hạn như một giá trị theo nghĩa đen hoặc giá trị được trả về do lệnh gọi hàm hoặc do tính toán một đoạn của biểu thức.
Loại LValue
có bản chất mở rộng, tức là, nằm trong nó cho phép đặt đối tượng có liên quan ở bên trái của =
nhưng không cấm sử dụng nó, ngang bằng với RValue
, ở bên phải của =
.
Loại RValue
, một lần nữa, có bản chất hạn chế, tức là, bất kỳ RValue
nào chỉ có thể ở bên phải của =
.
Vì một phần tử LValue
nhất định được sử dụng ở bên phải của '=', nên định danh của nó, trên thực tế, biểu thị nội dung hiện tại của nó được đặt vào công thức biểu thức.
Tuy nhiên, nếu một phần tử của LValue
được sử dụng ở bên trái của '=', định danh của nó biểu thị địa chỉ bộ nhớ (ô) nơi giá trị mới (kết quả tính toán biểu thức) sẽ được ghi.
Các toán tử khác nhau có những hạn chế khác nhau liên quan đến việc chúng có thể được sử dụng cho các toán hạng của LValue
hay RValue
hay không. Ví dụ, toán tử tăng '++' và giảm '--' (xem phần Tăng và Giảm) chỉ có thể được sử dụng với LValue
.
Sau đây là một số ví dụ về những điều được phép và không được phép làm với toán tử gán (script ExprAssign.mq5
):
// mô tả các biến
const double cx = 123.0;
int x, y, a[5] = {1};
string s;
// assignment
a[2] = 21; // ok
x = a[0] + a[1] + a[2]; // ok
s = Symbol(); // ok
cx = 0; // biến hằng số không thể thay đổi
// error: 'cx' - hằng số không thể được sửa đổi
5 = y; // 5 – this number (literal)
// error: '5' - l-value required
x + y = 3; // to the left of RValue (expression computation result)
// error: l-value required
Symbol() = "GBPUSD"; // to the left of RValue with the function call result
// error: l-value required
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Trình biên dịch trả về lỗi vi phạm quy tắc sử dụng toán tử.