[Lập trình C] Toán tử và biểu thức

Posted on December 28th, 2020

Bài học tiếp theo trong lập trình C đó là về toán tử và biểu thức. Bài này sẽ giúp bạn hiểu về các toán tử, thứ tự ưu tiên của các toán tử trong biểu thức. Qua đó, bạn sẽ hiểu được cách một biểu thức được thực hiện tính toán như thế nào.

Lý thuyết cơ bản về toán tử và biểu thức trong lập trình C

Các loại toán tử

Toán tử gán

Toán tử gán (=) dùng để gán giá trị của một biểu thức cho một biến.

Ví dụ:

int x = 6;
int y = 2 * x + 4;

Ta có thể gán cùng một giá trị cho nhiều biến với một dòng lệnh.

Ví dụ:

int x, y, z, t;
x = y = z =  t = 6;

Toán tử số học

Toán tử số học được dùng để biểu diễn các phép toán số học.

Các toán tử số học bao gồm: cộng(+), trừ(-), nhân(*), chia nguyên(/), chia dư(%)

Ví dụ:

int x = 6, y = 8, c;
c = 3 * x + y;

Toán tử quan hệ (so sánh)

Toán tử quan hệ dùng để so sánh giá trị giữa 2 biến, hoặc giữa 1 biến và 1 hằng số.

Các loại toán tử quan hệ bao gồm: lớn hơn (>), lớn hơn hoặc bằng (>=), nhỏ hơn (<), nhỏ hơn hoặc bằng (<=), bằng (==), khác (!=).

Kết quả của toán tử này sẽ trả về giá trị đúng (1) hoặc sai (0)

Ví dụ:

int x = 6;
int y = 8;
// x > y => sai
// x >= y => sai
// x < y => đúng
// x <= y => đúng
// x == y => sai
// x != y => đúng

Toán tử logic

Toán tử logic dùng để tổng hợp những biểu thức chứa toán tử quan hệ.

Các toán tử logic: AND(&&), OR(||), NOT(!)

Cách hoạt động của toán tử AND(&&):

1 && 1 // true
1 && 0 // false
0 && 1 // false
0 && 0 // false

Cách hoạt động của toán tử OR(||):

1 || 1 // true
1 || 0 // true
0 || 1 // true
0 || 0 // false

Cách hoạt động của toán tử NOT(!)

!0 // true
!1 // false

Toán tử logic bit

Toán tử logic bit là toán tử logic được áp dụng trên đối tượng là bit.

Các toán tử bit là: AND(&), OR(|), XOR(^), NOT(~)

Khi thực hiện với toán tử bit, các toán hạng sẽ được quy đổi sang số hệ nhị phân. Sau đó, ta sẽ thực hiện toán tử bit với các bit ở vị trí tương ứng nhau.

Cách hoạt động của toán tử bit AND(&):

1 & 1 // 1
1 & 0 // 0
0 & 1 // 0
0 & 0 // 0

Cách hoạt động của toán tử bit OR(|):

1 | 1 // 1
1 | 0 // 1
0 | 1 // 1
0 | 0 // 0

Cách hoạt động của toán tử bit XOR(^):

1 | 1 // 0
1 | 0 // 1
0 | 1 // 1
0 | 0 // 0

Cách hoạt động của toán tử bit NOT(~):

~1 // 0
~0 // 1

Cách biểu diễn số ở các hệ cơ số khác nhau:

int x = 0b1011;       // hệ số 2
int y = 0x12ab;       // hệ số 16
int z = 016760;       // hệ số 8
printf("x=%d\n", x);
printf("y=%d\n", y);
printf("z=%d\n", z);

Chuyển đổi kiểu dữ liệu

  • Là việc chuyển đổi một biến từ kiểu dữ liệu này sang kiểu dữ liệu khác.
  • Có 2 kiểu chuyển đổi dữ liệu: tự động (trình biên dịch), thủ công (ép kiểu)

Chuyển đổi kiểu dữ liệu tự động

  • Được thực hiện bởi trình biên dịch (compiler)
  • Việc chuyển đổi này xảy ra khi trong biểu thức có nhiều hơn một kiểu dữ liệu.
  • Khi đó, các kiểu dữ liệu sẽ được chuyển thành kiểu dữ liệu lớn nhất trong các kiểu dữ liệu xuất hiện ở biểu thức.
  • Thứ tự chuyển đổi từ kiểu dữ liệu nhỏ sang kiểu dữ liệu lớn hơn

lap-trinh-c-toan-tu-bieu-thuc--type-conversion

Ép kiểu dữ liệu (casts)

  • Chủ động ép một kiểu dữ liệu này sang kiểu dữ liệu khác.
  • Cú pháp: (type) data
  • Ví dụ:
float x, f;
f = 3.14159;
x = (int) f; // giá trị của x sẽ là 3

Thứ tự ưu tiên của các toán tử

  • Trong biểu thức có nhiều toán tử, mỗi toán tử có một mức độ ưu tiên khác nhau.
  • Toán tử có độ ưu tiên cao hơn sẽ được thực hiện trước.
  • Khi các toán tử có độ ưu tiên giống nhau thì thứ tự thực hiện là từ trái sang phải hoặc từ phải sang trái.

Thứ tự ưu tiên của một số toán tử số học

Thứ tự ưu tiên giảm dần từ trên xuống dưới.

- ++ -- // Right to left
* / %   // Left to right
+ -     // Left to right
=       // Left to right

Thứ tự ưu tiên của các toán tử so sánh

Các toán tử so sánh có thứ tự ưu tiên giống nhau, nên chúng luôn thực hiện từ trái sang phải

int t = 11;
int x = 0 < t <= 10;          // 1
int y = 0 < t && t <= 10;     // 0
int z = (0 < t) && (t <= 10); // 0

Thứ tự ưu tiên của các toán tử logic

Thứ tự ưu tiên là: NOT, AND, OR. Trường hợp nhiều toán tử NOT, AND, OR thì sẽ thực hiện theo thứ tự từ phải sang trái.

Ví dụ:

int t = 0 || 1 && !0 && 1; // 1
/*
t = 0 || 1 && 1 && 1;
t = 0 || 1 && 1
t = 0 || 1
t = 1
*/

So sánh thứ tự ưu tiên

So sánh thứ tự ưu tiên của các toán tử số học, so sánh, logic: toán tử số học > toán tử so sánh > toán tử logic.

Ví dụ:

int t = 2 * 3 + 4 / 2 > 3 && 3 < 5 || 10 < 9; // 1
/*
t = 6 + 2 > 3 && 3 < 5 || 10 < 9
t = 8 > 3 && 3 < 5 || 10 < 9
t = 1 && 1 || 0
t = 1 || 0
t = 1
*/

Thay đổi thứ tự ưu tiên

Có thể sử dụng cặp dấu ngoặc () để thay đổi thứ tự ưu tiên. Hay nói cách khác thì cặp () có thứ tự ưu tiên cao nhất.

Do đó, toán tử có độ ưu tiên thấp mà đặt trong cặp dấu () thì vẫn sẽ được thực hiện trước.

Ngoài ra, trong trường hợp có nhiều cặp () lồng nhau thì cặp () trong cùng sẽ thực hiện trước.

Trường hợp các cặp () ngang nhau thì sẽ thực hiện từ trái sang phải.

Bài tập thực hành về nhập xuất dữ liệu trong lập trình C

Cho int x = 1, y = 2, z = 3;

Tính giá trị của t1, t2, t3, t4 (các câu hỏi sau là độc lập với nhau)

int t1 = x++ + 3 * y / 5 + --z;
int t2 = 1.5 * y / 4 + x / 2 + (float)z / 6;
int t3 = 3.4 * x - 3 / y && 2 * z - y || x - 1;
int t4 = -2 * z + 6 + !(x * y - z) && y % (2 * z - 3);
int t1 = x++ + 3 * y / 5 + --z;
/*
t1 = 1 + 3 * 2 / 5 + 2
t1 = 1 + 1 + 2 
t1 = 4
*/

int t2 = 1.5 * y / 4 + x / 2 + (float)z / 6;
/*
t2 = 1.5 * 2 / 4 + 1 / 2 + 0.5
t2 = 0.75 + 0 + 0.5 
t2 = 1.25
t2 = 1 // t2 kiểu nguyên
*/

int t3 = 3.4 * x - 3 / y && 2 * z - y || x - 1;
/*
t3 = 3.4 - 3 / 2 && 2 * 3 - 4 || 0
t3 = 3.4 - 1.5 && 2 * 3 - 4 || 0
t3 = 3.4 - 1.5 && 2 || 0
t3 = 1.9 && 2 || 0
t3 = 1 || 0
t3 = 1
*/

int t4 = -2 * z + 6 + !(x * y - z) && y % (2 * z - 3);
/*
t4 = -2 * 3 + 6 + !(x * y -z) && y % (2 * 3 - 3)
t4 = -2 * 3 + 6 + 0 && 2 % 3
t4 = 0 && 2
t4 = 0
*/