Cộng đồng chia sẻ tri thức Doc24.vn

Khái niệm cơ bản Concept

Gửi bởi: Phạm Thọ Thái Dương vào ngày 2019-12-30 02:35:00 || Kiểu file: DOC Lượt xem: 328 | Lượt Download: 0 | File size: 0.18176 Mb

Nội dung tài liệu Xem trước tài liệu

Link tài liệu:
Tải xuống

Các tài liệu liên quan

Thông tin tài liệu

Toán tử và Biểu thức

Bài 4
Mục tiêu:
Kết thúc bài học này, bạn có thể:







Hiểu được Toán tử gán
Hiểu được biểu thức số học
Nắm được toán tử quan hệ (Relational Operators) và toán tử luận lý (Logical Operators)
Hiểu toán tử luận lý nhị phân (Bitwise Logical Operators) và bi ểu thức (Expressions)
Hiểu khái niệm ép kiểu
Hiểu độ ưu tiên của các toán tử.

Kết thúc bài học này, các học viên có thể:
 Nắm được Toán tử gán
 Hiểu được biểu thức số học
 Nắm được toán tử quan hệ (toán tử so sánh-Relational Operators) và toán t ử luận lý (Logical
Operators)
 Hiểu toán tử luận lý nhị phân( toán tử luận lý nhị phân-Bitwise Logical Operators) và bi ểu th ức
 Nắm được về ép kiểu qua Cast
 Hiểu về độ ưu tiên của các toán tử
Giới thiệu
C có một tập các toán tử phong phú. Toán tử là công c ụ dùng đ ể thao tác d ữ li ệu. M ột toán t ử là
một ký hiệu dùng để đại diện cho một thao tác cụ thể nào đó được thực hi ện trên d ữ li ệu. C đ ịnh
nghĩa bốn loại toán tử: toán tử số học ( arithmetic), quan hệ (relational), luận lý (logical), và toán
tử luận lý nhị phân (bitwise). Bên cạnh đó, C còn có một số toán tử đặc biệt.
Toán tử thao tác trên hằng hoặc biến. Hằng hoặc biến này được gọi là toán h ạng ( operands). Biến
đã được đề cập ở các chương trước. Hằng là những giá trị cố định mà chương trình không thể thay
đổi. Hằng trong C có thể là bất cứ kiểu dữ liệu cơ bản nào. Toán tử được phân lo ại: toán t ử m ột
ngôi, hai ngôi hoặc ba ngôi. Toán tử một ngôi chỉ thao tác trên một ph ần t ử d ữ li ệu, toán t ử hai ngôi
trên hai phần tử dữ liệu và ba ngôi trên ba phần tử dữ liệu.
Ví dụ 4.1:
c = a + b;
Ở đây a, b, c là những toán hạng, dấu ‘=’ và dấu ‘+’ là những toán tử.
4.1

Biểu thức (Expressions)

Một biểu thức là tổ hợp các toán tử và toán hạng. Toán tử thực hiện các thao tác nh ư c ộng,
trừ, so sánh v.v... Toán hạng là những biến hay những giá trị mà các phép toán đ ược th ực
hiện trên nó. Trong ví dụ a + b, “a” và “b” là toán hạng và “+” là toán tử. Tất cả kết hợp
lại là một biểu thức.

Toán tử và Biểu thức

47

Trong quá trình thực thi chương trình, giá trị thực sự của biến (nếu có) s ẽ đ ược s ử d ụng cùng v ới
các hằng có mặt trong biểu thức. Việc đánh giá biểu thức được thực hi ện nh ờ các toán t ử. Vì v ậy,
mọi biểu thức trong C đều có một giá trị.
Các ví dụ về biểu thức là:
2
x
3+7
2×y+5
2 + 6 × (4 - 2)
z + 3 × (8 - z)

48

Lập trình cơ bản C

Ví dụ 4.2:
Roland nặng 70 kilograms, và Mark nặng k kilograms. Viết một biểu thức cho tổng cân nặng c ủa
họ. Tổng cân nặng của hai người tính bằng kilograms là 70 + k.
Ví dụ 4.3:
Tính giá trị biểu thức 4 × z + 12 với z = 15.
Chúng ta thay thế mọi z với giá trị 15, và đơn giản hóa biểu thức theo quy tắc: thi hành phép toán
trong dấu ngoặc trước tiên, kế đến lũy thừa, phép nhân và chia rồi phép cộng và tr ừ.
4 × z + 12 trở thành
4 × 15 + 12 =

(phép nhân thực hiện trước phép cộng)

60 + 12 =
72
Toán tử gán (Assignment Operator)
Trước khi nghiên cứu các toán tử khác, ta hãy xét toán tử gán (=). Ðây là toán t ử thông d ụng nh ất
cho mọi ngôn ngữ và mọi người đều biết. Trong C, toán tử gán có thể đ ược dùng cho b ất kỳ bi ểu
thức C hợp lệ. Dạng thức chung cho toán tử gán là:
Tên biến = biểu thức;
Gán liên tiếp
Nhiều biến có thể được gán cùng một giá trị trong một câu l ệnh đ ơn. Vi ệc này th ực hi ện qua cú
pháp gán liên tiếp. Ví dụ:
a = b = c =10;
Dòng mã trên gán giá trị 10 cho a, b,và c. Tuy nhiên, việc này không thể thực hiện lúc khai báo biến.
Ví dụ,
int a = int b = int c= 0;
Câu lệnh trên phát sinh lỗi vì sai cú pháp.
Biểu thức số học (Arithmetic Expressions)
Các phép toán thường được thực hiện theo một thứ tự cụ thể (hoặc riêng bi ệt) đ ể cho ra giá tr ị
cuối cùng. Thứ tự này gọi là độ ưu tiên (sẽ nói đến sau).
Các biểu thức toán học trong C được biểu diễn bằng cách s ử dụng toán t ử s ố h ọc cùng v ới các
toán hạng dạng số và ký tự. Những biểu thức này gọi là bi ểu th ức s ố h ọc ( Arithmetic
Expressions). Ví dụ về biểu thức số học là :
a * (b+c/d)/22;
++i % 7;
5 + (c = 3+8);

Toán tử và Biểu thức

49

Như chúng ta thấy ở trên, toán hạng có thể là hằng, bi ến hay kết h ợp c ả hai. H ơn n ữa, m ột bi ểu
thức có thể là sự kết hợp của nhiều biểu thức con. Chẳng hạn, trong biểu th ức đ ầu, c/d là một
biểu thức con, và trong biểu thức thứ ba c = 3+8 cũng là một biểu thức con.
4.2

Toán tử quan hệ (Relational Operators)

Toán tử quan hệ được dùng để kiểm tra mối quan h ệ giữa hai biến , hay giữa một biến và một hằng.
Ví dụ, việc xét số lớn hơn của hai số, a và b, được thực hiện thông qua dấu lớn hơn ( >) giữa hai
toán hạng a và b (a > b).

Trong C, true (đúng) là bất cứ giá trị nào khác không (0), và false (sai) là bất cứ giá trị nào bằng
không (0). Biểu thức dùng toán tử quan hệ trả về 0 cho false và 1 cho true. Ví dụ biểu thức sau :
a == 14 ;
Biểu thức này kiểm tra xem giá trị của a có bằng 14 hay không. Giá tr ị c ủa bi ểu th ức s ẽ là 0 (false)
nếu a có giá trị khác 14 và 1 (true) nếu nó là 14.
Bảng sau mô tả ý nghĩa của các toán tử quan hệ.
Toán tử
>
>=
<
<=
==
!=

Ý nghĩa
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ông bằng
Bảng 4.1: Toán tử quan hệ và ý nghĩa

4.3

Toán tử luận lý (Logical Operators) và biểu thức

Toán tử luận lý là các ký hiệu dùng để kết hợp hay phủ định biểu thức có ch ứa các toán t ử quan
hệ.
Những biểu thức dùng toán tử luận lý trả về 0 cho false và 1 cho true.
Bảng sau mô tả ý nghĩa của các toán tử luận lý.
Toán tử
&&
||
!

Ý nghĩa
AND: trả về kết quả là true khi cả 2
toán hạng đều true
OR : trả về kết quả là true khi chỉ một
trong hai toán hạng đều true
NOT: Chuyển đổi giá trị của toán hạng
duy nhất từ true thành false và ngược
lại.
Table 4.2: Toán tử luận lý và ý nghĩa

Lưu ý: Bất cứ toán tử luận lý nào có ký hiệu là hai ký tự thì không đ ược có khoảng tr ắng gi ữa hai
ký tự đó, ví dụ : == sẽ không đúng nếu viết là = =.

50

Lập trình cơ bản C

Giả sử một chương trình phải thực thi những bước nhất định nếu điều kiện a < 10 và b == 7 được
thoả mãn. Ðiều kiện này được viết ra bằng cách dùng toán tử quan h ệ kết h ợp v ới toán t ử lu ận lý
AND. Toán tử AND được viết là &&. Ta sẽ có điều kiện để kiểm tra như sau :
(a < 10) && (b == 7);
Tương tự, toán tử OR dùng để kiểm tra xem có một trong số các đi ều ki ện ki ểm tra là đúng hay
không. Nó có dạng là dấu (||). Cùng ví dụ trên nhưng điều kiện cần kiểm tra là: chỉ cần m ột trong
hai câu lệnh là đúng thì ta có mã sau :
(a < 10) || (b == 7);
Toán tử luận lý thứ ba là NOT được biểu diễn bằng ký hiệu dấu chấm than ‘ !’. Toán tử này đảo
ngược giá trị luận lý của biểu thức. Ví dụ, để kiểm tra xem biến s có bé h ơn 10 hay không, ta vi ết
đều kiện kiểm tra như sau:
(s < 10);
hay là
(! (s >= 10))

/* s không lớn hơn hay bằng 10 */

Cả toán tử quan hệ và luận lý có quyền ưu tiên thấp hơn toán tử số học . Ví dụ, 5 > 4 + 3 được tính
tương đương với 5 > (4 + 3), nghĩa là 4+3 sẽ được tính trước và sau đó toán tử quan hệ sẽ đ ược
thực hiện. Kết quả sẽ là false, tức là trả về 0.
Câu lệnh sau:
printf("%d", 5> 4 + 3);
sẽ cho ra:
0
vì 5 bé hơn (4 + 3) .
4.4

Toán tử luận lý nhị phân (Bitwise Logical Operators) và biểu thức

Ví dụ xét toán hạng có giá trị là 12, t oán tử luận lý nhị phân sẽ coi số 12 này như 1100. Toán tử
luận lý nhị phân xem xét các toán hạng dưới dạng chuỗi bit ch ứ không là giá tr ị s ố thông th ường.
Giá trị số có thể thuộc các cơ số: thập phân (decimal), bát phân (octal) hay th ập l ục phân
(hexadecimal). Riêng toán tử luận lý nhị phân s ẽ chuy ển đ ổi toán h ạng mà nó thao tác thành bi ểu
diễn nhị phân tương ứng, đó là dãy số 1 hoặc là 0.
Toán tử luận lý nhị phân gồm &, | , ^ , ~ , vv … được tổng kết qua bảng sau:.

Toán tử

Mô tả

Bitwise AND
( x & y)

Mỗi vị trí của bit trả về kết quả là 1 nếu bit
tại vị trí tương ứng của hai toán hạng đều là
1.

Toán tử và Biểu thức

51

Bitwise OR
( x | y)

Mỗi vị trí của bit trả về kết quả là 1 nếu bit
tại vị trí tương ứng của một trong hai toán
hạng là 1.

Bitwise NOT
( ~ x)

Ðảo ngược giá trị các bit của toán hạng (1
thành 0 và ngược lại).

Bitwise XOR
( x ^ y)

Mỗi vị trí của bit trả về kết quả là 1 nếu bit
tại vị trí tương ứng của một trong hai toán
hạng là 1 chứ không phải cả hai cùng là 1.
Bảng 4.3: Toán tử luận lý nhị phân

Toán tử luận lý nhị phân xem kiểu dữ liệu số như là số nhị phân 32-bit, giá tr ị số được đổi thành
giá trị bit để tính toán trước rồi sau đó sẽ trả về kết quả ở dạng số ban đầu. Ví dụ:
Biểu thức 10 & 15 có nghĩa là (1010 & 1111) trả về giá trị 1010 có nghĩa là 10.
Biểu thức 10 | 15 có nghĩa là (1010 | 1111) trả về giá trị 1111 có nghĩa là 15.
Biểu thức 10 ^ 15 có nghĩa là (1010 ^ 1111) trả về giá trị 0101 có nghĩa là 5.
Biểu thức ~10 có nghĩa là ( ~1010 ) trả về giá trị 1111.1111.1111.1111.1111.1111.1111.0101 có nghĩa
là -11.
4.5

Biểu thức dạng hỗn hợp & Chuyển đổi kiểu

Một biểu thức dạng hỗn hợp là một biểu thức mà trong đó các toán h ạng c ủa m ột toán t ử thu ộc v ề
nhiều kiểu dữ liệu khác nhau. Những toán hạng này thông thường được chuyển về cùng ki ểu với
toán hạng có kiểu dữ liệu l ớn nhất. Điều này được gọi là tăng cấp kiểu. Sự phát triển về kiểu dữ
liệu theo thứ tự sau :

char < int Chuyển đổi kiểu tự động được trình bày dưới đây nhằm xác định giá trị của biểu thức:
a.
b.
c.
d.
e.

char và short được chuyển thành int và float được chuyển thành double.
Nếu có một toán hạng là double, toán hạng còn lại sẽ được chuyển thành double, và kết
quả là double.
Nếu có một toán hạng là long, toán hạng còn lại sẽ được chuyển thành long, và kết quả là
long.
Nếu có một toán hạng là unsigned, toán hạng còn lại sẽ được chuyển thành unsigned và
kết quả cũng là unsigned.
Nếu tất cả toán hạng kiểu int, kết quả là int.

Ngoài ra nếu một toán hạng là long và toán hạng khác là unsigned và giá trị của kiểu unsigned
không thể biểu diễn bằng kiểu long. Do vậy, cả hai toán hạng được chuyển thành unsigned long.
Sau khi áp dụng những quy tắc trên, mỗi cặp toán hạng có cùng ki ểu và kết quả của mỗi phép tính
sẽ cùng kiểu với hai toán hạng.

52

Lập trình cơ bản C

char ch;
int i;
float f;
double d;
result = (ch/i) + (f*d) – (f+i);
int

double float

double
double
Trong ví dụ trên, trước tiên, ch có kiểu ký tự được chuyển thành integer và float f được chuyển
thành double. Sau đó, kết quả của ch/i được chuyển thành double bởi vì f*d là double. Kết quả
cuối cùng là double bởi vì các toán hạng lúc này đều là double.

Ép kiểu (Casts)

4.5.1

Thông thường, ta nên đổi tất cả hằng số nguyên sang kiểu float n ếu biểu th ức bao g ồm nh ững
phép tính số học dựa trên số thực, nếu không thì vài biểu th ức có th ể m ất đi giá tr ị th ật c ủa nó.Ta
xem ví dụ:
int
x =
y =
z =

x,y,z;
10;
100;
x/y;

Trong trường hợp này, z sẽ được gán 0 khi phép chia diễn ra và phần thập phân (0.10) sẽ bị cắt bỏ.
Do đó một biểu thức có thể được ép thành một kiểu nhất định. Cú pháp chung của cast là:
(kiểu dữ liệu) biểu thức
Ví dụ, để đảm bảo rằng biểu thức a/b, với a và b là số nguyên, cho kết quả là kiểu float, dòng mã
sau được viết:
(float) a/b;
Ép kiểu có thể áp dụng cho các giá trị hằng, biểu thức hay biến, ví dụ:
(int) 17.487;
(double) (5 * 4 / 8);
(float) (a + 7);
Trong ví dụ thứ hai, toán tử ép kiểu không đạt mục đích của nó b ởi vì nó ch ỉ th ực thi sau khi toàn
biểu thức trong dấu ngoặc đã được tính. Biểu thức 5 * 4 / 8 cho ra giá trị là 2 (vì nó có kiểu là số
nguyên nên đã cắt đi phần thập phân), vì vậy, giá trị kết quả với kiểu double cũng là 2.0.
Ví dụ:
Toán tử và Biểu thức

53

int i = 1, j = 3;
x = i / j;
/* x = 0.0 */
x = (float) i/(float) j;
/* x = 0.33 */
4.6

Độ ưu tiên của toán tử (Precedence)

Độ ưu tiên của toán tử thiết lập thứ tự ưu tiên tính toán khi m ột bi ểu th ức s ố h ọc c ần đ ược ước
lượng. Tóm lại, độ ưu tiên đề cập đến thứ tự mà C thực thi các toán t ử. Thứ t ự ưu tiên c ủa toán t ử
số học được thể hiện như bảng dưới đây.
Loại toán tử
Một ngôi
Hai ngôi

Toán tử
- , ++, -^
*, /, %
+, =

Tính kết hợp
Phải sang trái
Trái sang phải
Phải sang trái

Bảng 4.4: Thứ tự ưu tiên của toán tử số học
Những toán tử nằm cùng một hàng ở bảng trên có cùng quyền ưu tiên. Vi ệc tính toán của m ột bi ểu
thức số học sẽ được thực hiện từ trái sang phải cho các toán tử cùng độ ưu tiên. Toán t ử *, /, và %
có cùng đô ưu tiên và cao hơn + và - (hai ngôi).
Độ ưu tiên của những toán tử này có thể được thay đổi bằng cách s ử d ụng d ấu ngo ặc đ ơn. M ột
biểu thức trong ngoặc luôn luôn được tính toán trước. Một cặp dấu ngoặc đơn này có thể được bao
trong cặp khác. Ðây là sự lồng nhau của những dấu ngoặc đơn. Trong trường hợp đó, việc tính toán
trước tiên được thực hiện tại cặp dấu ngoặc đơn trong cùng nhất r ồi đến d ấu ngoặc đ ơn bên
ngoài.
Nếu có nhiều bộ dấu ngoặc đơn thì việc thực thi sẽ theo thứ tự từ trái sang phải.
Tính kết hợp cho biết cách thức các toán tử kết h ợp v ới các toán h ạng c ủa chúng. Ví d ụ, đ ối v ới
toán tử một ngôi: toán hạng nằm bên phải được tính trước, trong phép chia thì toán h ạng bên trái
được chia cho toán hạng bên phải. Đối với toán tử gán thì bi ểu th ức bên phải đ ược tính tr ước rồi
gán giá trị cho biến bên trái toán tử.
Tính kết hợp cũng cho biết thứ tự mà theo đó C đánh giá các toán tử trong bi ểu th ức có cùng đ ộ ưu
tiên. Các toán tử như vậy có thể tính toán từ trái sang phải hoặc ngược l ại như th ấy trong b ảng 4.5.
Ví dụ:
a = b = 10/2;
Giá trị 5 sẽ gán cho b xong rồi gán cho a. Vì vậy thứ tự ưu tiên sẽ là phải sang trái. Hơn nữa,
-8 * 4 % 2 – 3
được tính theo trình tự sau:
Trình tự
1.
2.
3.
54

Thao tác
- 8 (phép trừ một ngôi)
-8*4
- 32 % 2

Kết quả
số âm của 8
- 32
0
Lập trình cơ bản C

4.

0-3

-3

Theo trên thì toán tự một ngôi (dấu - ) có quyền ưu tiên cao nh ất đ ược tính trước tiên. Gi ữa * và %
thì được tính từ trái sang phải. Tiếp đến sẽ là phép trừ hai ngôi.
Thứ tự ưu tiên của các biểu thức con
Những biểu thức phức tạp có thể chứa những biểu thức nhỏ hơn g ọi là biểu thức con. C không
xác định thứ tự mà các biểu thức con được lượng giá. Một biểu thức sau:
a * b /c + d *c;
bảo đảm rằng biểu thức con a * b/c và d*c sẽ được tính trước phép cộng. Hơn nữa, quy tắc từ trái
sang phải cho phép toán nhân và chia bảo đảm r ằng a sẽ được nhân với b và sau đó sẽ chia cho c.
Nhưng không có quy tắc xác định hoặc a*b /c được tính trước hay sau d*c. Tùy chọn này là ở
người thiết kế trình biên dịch quyết định. Quy tắc trái sang ph ải hay ng ược l ại ch ỉ áp d ụng cho
một chuỗi toán tử cùng độ ưu tiên. Cụ thể, nó áp dụng cho phép nhân và chia trong a*b/c. Nhưng
nó không áp dụng cho toán tử + vì đã khác cấp.
Bởi vì không thể xác định thứ tự tính toán các biểu thức con, do v ậy, ta không nên dùng các bi ểu
thức nếu giá trị biểu thức phụ thuộc vào thứ tự tính toán các biểu thức con . Xét ví dụ sau:
a * b + c * b++ ;
Có thể trình biên dịch này tính giá trị mục bên trái trước và dùng cùng giá tr ị b cho cả hai biểu thức
con. Nhưng trình biên dịch khác lại tính giá trị mục bên phải và tăng giá tr ị b trước khi tính giá trị
mục bên trái.
Ta không nên dùng toán tử tăng hay giảm cho một biến mà nó xu ất hi ện nhi ều h ơn m ột l ần trong
một biểu thức.
Thứ tự ưu tiên giữa những toán tử so sánh (toán tử quan hệ)
Ta đã thấy trong phần trước một số toán tử số học có độ ưu tiên cao h ơn các toán t ử s ố h ọc khác.
Riêng với toán tử so sánh, không có thứ tự ưu tiên giữa các toán t ử và chúng đ ược ước lượng từ trái
sang phải.
Thứ tự ưu tiên giữa những toán tử luận lý
Bảng dưới đây trình bày thứ tự ưu tiên cho toán tử luận lý.
Thứ tự

Toán tử

1

NOT

2

AND

3

OR

Bảng 4.5: Thứ tự ưu tiên cho toán tử luận lý
Khi có nhiều toán tử luận lý trong một điều kiện, chúng được lượng giá từ phải sang trái .
Ví dụ, xét điều kiện sau:
Toán tử và Biểu thức

55

False OR True AND NOT False AND True
Ðiều kiện này được tính như sau:
1. False OR True AND [NOT False] AND True
NOT có độ ưu tiên cao nhất.
2. False OR True AND [True AND True]
Ở đây, AND là toán tử có độ ưu tiên cao nhất và những toán tử có cùng ưu tiên được tính từ
phải sang trái.
3. False OR [True AND True]
4.

[False OR True]

5. True
Thứ tự ưu tiên giữa các kiểu toán tử khác nhau
Khi một biểu thức có nhiều hơn một kiểu toán tử thì t hứ tự ưu tiên phải được thiết lập giữa các
kiểu toán tử với nhau.
Bảng dưới đây cho biết thứ tự ưu tiên giữa các kiểu toán tử khác nhau.

Thứ tự

Kiểu toán tử

1

Số học

2

So sánh (Quan hệ)

3

Luận lý

Bảng 4.6. Thứ tự ưu tiên giữa các kiểu toán tử khác nhau
Do vậy, trong một biểu thức gồm cả ba kiểu toán tử, các toán tử số học được tính trước, kế đến là
toán tử so sánh và sau đó là toán tử luận lý . Thứ tự ưu tiên của các toán tử trong cùng một kiểu thì
đã được nói tới ở những phần trước.
Xét ví dụ sau:
2*3+4/2 > 3 AND 3<5 OR 10<9
Việc thực hiện tính toán sẽ như sau:
1. [2*3+4/2] > 3 AND 3<5 OR 10<9
Ðầu tiên toán tử số học sẽ được tính theo thứ tự ưu tiên như bảng 4.4.
2. [[2*3]+[4/2]] > 3 AND 3<5 OR 10<9
3. [6+2] >3 AND 3<5 OR 10<9

56

Lập trình cơ bản C