Trong toán học, chúng ta biết rằng khi tính giá trị của một biểu thức, thì luôn có sự ưu tiên của các toán tử như: phép nhân thực hiện trước phép cộng, phép chia và nhân thực hiện đồng thời, ưu tiên từ trái sang phải… Trong các ngôn ngữ lập trình nói chung cũng như C++ nói riêng, các toán tử cũng có những độ ưu tiên nhất định. Trong một biểu thức phức tạp, ta cần chú ý đến độ ưu tiên của các toán tử, điều này rất dễ gây ra sai sót. Trong bảng sau đây, tôi xin đưa ra thứ tự ưu tiên của các toán tử trong lập trình C++.
Mức ưu tiên Toán tử Độ ưu tiên cùng loại
1 :: Trái-sang-phải
2 () [] . -> ++ -- (hậu tố) dynamic_cast static_cast reinterpret_cast const_cast typeid
Trái-sang-phải
3 ++ -- (tiền tố) ~ ! sizeof new delete Phải-sang-trái * &
C
+
+
4 (type) (chuyển đổi kiểu) Phải-sang-trái
5 .* ->* Trái-sang-phải
6 * / % Trái-sang-phải
7 + - (phép toán công, trừ) Trái-sang-phải
8 << >> Trái-sang-phải 9 < > <= >= Trái-sang-phải 10 == != Trái-sang-phải 11 & Trái-sang-phải 12 ^ Trái-sang-phải 13 | Trái-sang-phải 14 && Trái-sang-phải 15 || Trái-sang-phải 16 ?: Phải-sang-trái 17 = *= /= %= += -= >>= <<= &= ^= |= Phải-sang-trái 18 , Trái-sang-phải
Các toán tử được thực hiện theo mức ưu tiên từ trên xuống. Nếu các toán tử
cùng mức, nó sẽ được thực hiện theo độ ưu tiên cùng loại.
Ví dụ:
a = (b=0, c=0, b+c). Toán tử gán = có độ ưu tiên 17, các toán tử cộng + có
độ ưu tiên 7, toán tử () có độ ưu tiên 2 và toán tử , có độ ưu tiên 18. Do đó, toán tử () sẽ được thực hiện trước. Bây giờ ta xét các toán tử trong dấu (), chú ý rằng các biểu thức b=0, c=0, b+c là các biểu thức riêng biệt, chúng được phân tách bởi toán tử phân tách (,). Theo thứ tự ưu tiên của toán tử phẩy, nó sẽ thực hiện từ trái-sang-phải. Nghĩa là b=0, c=0 sau đó là b+c. Cuối cùng nó sẽ thực hiện toán tử gán giá trị của biểu thức phức hợp bên phải cho bên trái. Kết quả là 0.
a = (1+2)*3/2++. Toán tử gán (độ ưu tiên 17), toán tử + (độ ưu tiên 7), toán
tử * (độ ưu tiên 6), toán tử / (độ ưu tiên 6), toán tử ++ hậu tố (độ ưu tiên 2) và toán tử () (độ ưu tiên 2). Toán tử hậu tố ++ và toán tử () sẽ thực hiện trước. Theo độ ưu tiên cùng loại, nó sẽ thực thi từ trái-sang-phải. Như vậy, toán tử () sẽ được thực hiện đầu tiên. Nghĩa là ta nhận được biểu thức a = 3*3/2++. Tiếp theo, nó thực hiện toán tử hậu tố ++, tuy nhiên toán tử này chỉ tăng giá trị của 2 lên 1 sau khi thực hiện xong các phép toán trong biểu thức. Đến thời điểm này, ta nhận được biểu thức a=3*3/2. Toán tử * và / có cùng độ ưu tiên, nó sẽ được thực hiện theo thứ trự từ trái sang phải, nghĩa là a=9/2=4. Kết quả 4.
Lưu ý. Trong ví dụ thứ hai, việc sử dụng phép toán 2++ là không hợp lệ. Ở đây,
chỉ có tác dụng minh họa trực quan. Còn 2 là một hằng số, ta không thể thực hiện phép toán 2++ để làm thay đổi giá trị của hằng. Trong C++, chúng ta cần thực hiện phép gán b = 2; sau đó là b++. Nghĩa là ta cần biểu diễn biểu thức như sau để thu được một kết quả chính xác có thể bảo đảm thực thi được trong C++.
C
+
+
a = (b=2, (1+2)*3/b++) Bài tập 4.
Tính toán các biểu thức sau, dựa vào độ ưu tiên của toán tử, sau đó, viết chương trình trên C++ để kiểm tra kết quả.
a. 2+2*4%3+ ++2; b. 2++ + ++2*(3-- - --2) c. 5++ - 3== --2-(4+2%3) d. 5>>2^3*(1+2)