
Chương 3
Hàm (Function)
Lập trình đơn thể
M
ỗ
i module có d
ữ
li
ệ
u riêng
độ
c l
ậ
p v
ớ
i module khác
Main Program(Also a module)
Data
Module
1
+
Data Data
1
Procedure
1
Module
2
+
Data Data
2
Procedure
2
Procedure
3
Lập trình đơn thể(tt)
“Chia để trị”: phân rã bài toán thành các bài
toán con cho đến khi “bài toán con” nhận
được “đủ nhỏ”.
Mỗi “bài toán con” được giải quyết bằng một
module, độc lập với các module khác.
Trong C mỗi module chính là 1 hàm.
Phân tích: top down.
Thiết kế: bottom up.
Lập trình đơn thể(tt)
Bài toán ban đầu
module1 module2 ...
module11 module12
modulek
...
phân tích
thiết kế
Ưu điểm của phương pháp lập trình đơn thể?

Cú pháp của hàm
<type_function> f_name(parameters)
{
/* các khai báo cục bộ*/
/* các câu lệnh */
[return <Exp>;] /* có thểcó hoặc không*/
}
Cú pháp của hàm (tt)
Ví d
ụ
1:
void chao()
{
printf(“\nxin chao”);
}
Ví d
ụ
2:
int tong(int n)
{
int i,t=0;
for(i=1;i<=n;++i)t=t+i;
return t;
}
Cú pháp của hàm (tt)
Ví dụ3:
int ucln(int x, int y)
{
while(x*y)
if(x>y)x=x%y;
else y=y%x;
return (x+y);
}
Lời gọi hàm
Ví dụ:
chao();
kq1=tong(12); kq2=tong(kq1);
kq3=ucln(kq1,15);
Có thểkhông có
<tên_hàm>([danh sách tham sốthực])

Các bước thực hiện lời gọi hàm
Giảsửint a, b, kq; là các biến toàn cục và
a=6; b=8;
Xét lời gọi hàm: kq = ucln(a,b); (*)
Khi đó các bước sau đây được thực hiện:
B1: Lưu địa chỉcủa câu lệnh kếtiếp sau lời gọi
hàm (*) làm địa chỉquay vềsau khi kết thúc
hàm.
B2: Cấp phát vùng nhớcho các tham sốvà các
biến cục bộ.
Các bước thực hiện lời gọi hàm (tt)
6 8
a b
Data Segment
Stack Segment
x y
kq
(bước 2)
Các bước thực hiện lời gọi hàm (tt)
B3: Sao chép giá trịcủa tham sốthực
cho tham sốhình thức
6 8
a b
6 8
x y
kq
Các bước thực hiện lời gọi hàm (tt)
B4: Thực hiện các câu lệnh trong thân
hàm.
6 8
a b
0 2
x y
kq

Các bước thực hiện lời gọi hàm (tt)
B5: Trảlại kết quảbởi lệnh return.
6 8
a b
0 2
x y
kq
2
Các bước thực hiện lời gọi hàm (tt)
B6: Giải phóng các
vùng nhớ đã cấp phát
ởB2, lấy địa chỉ đã
lưu ởB1 thực hiện
tiếp chương trình.
6 8
a b
2
kq
Cơ chếtruyền tham trị
Giá trịcủa tham sốthực được sao chép
cho tham sốhình thức.
Tham sốthực luôn luôn được bảo toàn.
Như ởví dụtrên giá trịcủa a và b sau
khi thực hiện (*) vẫn không thay đổi
(trong khi x và y đã thay đổi).
Con trỏ(pointer) và cơ chế truyền
địa chỉ
Định nghĩa: con trỏlà biến dùng để chứa
địa chỉcủa biến khác.
Khai báo:
Ví dụ:
<kiểu_ct> *<tên_ct>;
int *p;
Khai báo con trỏ
kiểu nguyên int

Cách sửdụng con trỏ
Dùng tên con tr
ỏ
, gi
ố
ng nh
ư
m
ộ
t bi
ế
n bình th
ườ
ng.
Dùng d
ạ
ng khai báo *<tên_ct>, cho k
ế
t qu
ả
là d
ữ
li
ệ
u
mà con tr
ỏ đang
“tr
ỏ
” t
ớ
i.
Có th
ể
dùng các phép toán
đố
i v
ớ
i con tr
ỏ
(ph
ầ
n sau)
Ví d
ụ
:
int x=13, *p;
p=&x; //p tr
ỏ
t
ớ
i x.
printf(“\n%d duoc luu tai dia chi %p”,x,p);
printf(“\np dang tro toi du lieu la %d”,*p);
Cách sửdụng con trỏ(tt)
13
&x
x=*p
p
Truyền địa chỉ
Trong những trường hợp cần làm cho
tham sốthực bị thay đổi thì phương
pháp truyền tham trị không đáp ứng
được. Vậy cần có một phương pháp
khác, đó là:
Tham sốhình thức nhận địa chỉcủa
tham sốthực (nên tham sốhình thức
phải là một con trỏ).
Truyền địa chỉ
Ví dụ:
void hoan_vi(int *x, int *y)
{
int t=*x;
*x=*y;
*y=t;
}
Giảsửint a,b là các biến toàn cục và a=5; b=7;
Xét lời gọi hàm: hoan_vi(&a,&b); khi đó:

