Bài 11 · Vận dụng · 22 phút· Cập nhật 11/06/2026
Hàm
Biên soạn bởi Nguyễn Anh Tuấn
Tách chương trình thành hàm: parameter/argument, return/void, prototype, scope và pass by value.
Hàm (function) gói một việc thành khối có tên, viết một lần rồi gọi nhiều nơi. Một hàm gồm bốn phần: kiểu trả về · tên · danh sách tham số · thân. Trong thân, return gửi kết quả về cho nơi gọi:
ham-co-ban.c
#include <stdio.h>
int cong(int a, int b) { // tra ve int; ten 'cong'; 2 tham so
return a + b; // gui ket qua ve
}
int main() {
int tong = cong(3, 4); // goi ham, doi so 3 va 4
printf("%d\n", tong);
return 0;
} Kết quả khi chạy
7
- ▸Cú pháp: kiểu_trả_về tên(tham_số) { thân; return …; }
- ▸Tham số = biến trong định nghĩa; đối số = giá trị thực khi gọi.
- ▸main cũng là một hàm - chương trình bắt đầu chạy từ đó.
Hãy hình dung hàm như một chiếc máy: truyền đối số vào, nó tính toán rồi return kết quả ra. Chọn hàm và đổi đối số để xem từng đối số được gán vào tham số nào và hàm trả về gì:
int cong(int a, int b) { return a + b; }
Hàm nhận đối số vào các tham số, tính toán, rồi return một giá trị về cho nơi gọi - như một chiếc máy: bỏ nguyên liệu vào, nhận sản phẩm ra.
binh-phuong.c
#include <stdio.h>
int binhPhuong(int x) {
return x * x;
}
int main() {
printf("%d\n", binhPhuong(5));
return 0;
} Kết quả khi chạy
25
Không phải hàm nào cũng cần trả giá trị. void nghĩa là “rỗng” - không trả về gì; hàm chỉ thực hiện một việc (vd in ra màn hình):
ham-void.c
#include <stdio.h>
void chao(char ten[]) { // void: khong tra ve
printf("Xin chao, %s!\n", ten);
}
int main() {
chao("Lan");
chao("Nam");
return 0;
} Kết quả khi chạy
Xin chao, Lan! Xin chao, Nam!
- ▸void = không trả về giá trị; chỉ tạo “tác dụng phụ” (side effect) như in ra.
- ▸Trong hàm void có thể dùng return; (không kèm giá trị) để thoát sớm.
- ▸Viết một việc thành hàm rồi gọi nhiều lần → tránh lặp code.
Biến khai báo trong hàm là cục bộ - chỉ sống trong hàm đó. Và C truyền theo giá trị: hàm nhận một bản sao của đối số, nên sửa tham số bên trong không đổi biến gốc ở nơi gọi:
truyen-gia-tri.c
#include <stdio.h>
void thuTangGap(int n) {
n = n * 2; // chi doi BAN SAO
printf("Trong ham: %d\n", n);
}
int main() {
int x = 5;
thuTangGap(x);
printf("Sau khi goi: %d\n", x); // x VAN la 5
return 0;
} Kết quả khi chạy
Trong ham: 10 Sau khi goi: 5
Muốn hàm sửa được biến gốc?
Lỗi phổ biến nhất với người mới: gọi hàm trước khi trình biên dịch biết nó. Trình biên dịch đọc từ trên xuống - nếu hàm định nghĩa BÊN DƯỚI main, tới chỗ gọi nó chưa biết hàm là gì:
thieu-prototype.c
#include <stdio.h>
int main() {
printf("%d\n", cong(2, 3)); // LOI: 'cong' chua duoc khai bao
return 0;
}
int cong(int a, int b) { return a + b; } Kết quả khi chạy
Loi bien dich: 'cong' undeclared
Cách sửa & lỗi quên return
Câu hỏi thường gặp
Hàm giúp (1) tái sử dụng: viết một lần, gọi nhiều nơi; (2) đặt tên cho một việc → code dễ đọc; (3) chia nhỏ bài toán để dễ kiểm thử. Chương trình lớn mà nhồi hết vào main thì rối và lặp lại rất nhiều.
Tham số là tên biến ghi trong định nghĩa hàm - int cong(int a, int b) thì a, b là tham số. Đối số là giá trị thực truyền vào khi gọi - cong(3, 4) thì 3, 4 là đối số. Khi gọi, đối số được “gán” vào tham số.
return trả một giá trị về cho nơi gọi và kết thúc hàm ngay. Hàm void không trả gì - nó chỉ làm việc (vd in ra màn hình); có thể viết một lệnh return; không kèm giá trị để thoát sớm.
C truyền theo GIÁ TRỊ (pass by value): hàm nhận một BẢN SAO của đối số. Sửa bản sao không động tới bản gốc. Muốn hàm sửa được biến gốc phải truyền địa chỉ (con trỏ) - chủ đề của khoá C nâng cao.
Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.
Trả lời vài câu để chắc rằng em đã nắm bài.
Phân biệt tham số (parameter) và đối số (argument) theo bài?
- 1
Hàm cộng
Viết hàm
int cong(int a, int b)trả về tổng, rồi gọicong(15, 27)trongmainvà in kết quả.Hoàn thành khi:
int cong(int a, int b) { return a + b; }→ in 42. - 2
Bình phương
Dùng công cụ Bước 2: chọn hàm
binhPhuong, đặtx = 7. Nó trả về bao nhiêu?Hoàn thành khi: 49 (7 × 7). Thân hàm là
return x * x; - 3
Chu vi hình chữ nhật
Dùng công cụ: chọn
chuViHCNvớidai = 5,rong = 3. Kết quả? Viết lại công thức trong thân hàm.Hoàn thành khi: 16 -
return (dai + rong) * 2;với (5+3)*2 = 16. - 4
Truyền theo giá trị
Hàm
void thuTangGap(int n)đặtn = n*2. Sau khi gọithuTangGap(x)vớix = 5,maininxra bao nhiêu?Hoàn thành khi: 5 - hàm chỉ đổi bản sao; biến
xởmainkhông đổi. - 5
Hàm void chào
Viết hàm
void chao(char ten[])in “Xin chao, <ten>!”. Gọi với"Lan"và"Nam".Hoàn thành khi:
void chao(char ten[]) { printf("Xin chao, %s!\n", ten); }- không córeturngiá trị. - 6
Số chẵn?
Viết hàm
int laChan(int n)trả về 1 nếunchẵn, 0 nếu lẻ (dùng%).laChan(8)ra gì?Hoàn thành khi:
return n % 2 == 0;→laChan(8)= 1 (chẵn).