1.Hàm là gì?

Một nhóm các câu lệnh đều có chung một nhiệm vụ sẽ được gom vào thành một hàm, hay hiểu nôm na rằng hàm chính là cái để chứa một hay nhiều nhóm các câu lệnh cùng thực hiện một tác vụ nào đó. Mọi chương trình C đều phải có ít nhất một hàm, đó là hàm main() mà ta vẫn thường sử dụng cho những bài trước. Ngoài ra ta còn có thể tự định nghĩa thêm các hàm với cho mục đích khác nhau, cho các chức năng khác nhau trong chương trình.

2.Khai báo hàm trong C

Để sử dụng hàm trong C ta khai báo với cú pháp sau:

return_type name( parameter list) {
   CodeBlock;
   return result;
}

Trong đó:

  • Return_type: Là kiểu dữ liệu mà ta mong muốn hàm trả về (xem lại bài kiểu dữ liệu ở bài 1)
  • Name: là tên hàm mà ta sẽ đặt bất kỳ
  • Parameter list: Là các tham số đầu vào của hàm
  • CodeBlock: Là các khối lệnh có cùng tác vụ trong hàm
  • Return result: Là kết quả mà hàm trả về sau khi thực hiện việc gọi hàm ra để sử dụng

Chú ý: Định nghĩa hàm có kiểu trả về là void thì không cần phải trả về dữ liệu trong hàm (Ví dụ 2)

3.Gọi và sử dụng hàm trong C

  • Để sử dụng được hàm mà ta vừa tự định nghĩa ta cần gọi hàm đó trong hàm main() bằng cách gọi: name(parameter list)
  • Nếu hàm có tham số thì phải chuyền đủ tham số vào trong hàm sau khi gọi hàm đó trong main()
  • Tham số truyền vào phải có cùng kiểu dữ liệu với Return_type: Là kiểu dữ liệu mà ta mong muốn hàm trả về

Ví dụ (1) dưới đây, tôi tự định nghĩa một hàm mới bên ngoài hàm main và khai báo hàm có kiểu dữ liệu trả về là int để thực hiện việc tính tổng của hai số a, b do người dùng nhập vào từ bàn phím:

#include <stdio.h>
// Dinh nghia mot ham sum co chuc nang tinh tong 2 so a,b dau vao
int sum(int a, int b){
    //Thuc hien tinh tong a,b
    int sum = a + b;
    //Tra ve ket qua cho ham
    return sum;
}
int main () {
   // Khai bao hai bien a,b
   int a,b;
   //Nhap a tu ban phim
   printf("Nhap a: \n");
   scanf("%d",&a);
   //Nhap b tu ban phim
   printf("Nhap b: \n");
   scanf("%d",&b);
   // Goi ham sum truyen tham so a,b vao va kiem tra ket qua
   printf("Ket qua tinh tong a,b la: %d",sum(a, b));
   return 0;
}
Nhap a:

5

Nhap b:

6

Ket qua tinh tong a,b la: 11

Ví dụ (2) tiếp theo, tôi khai báo một hàm đặc biệt, có kiểu dữ liệu trả về là void để thực hiện việc nhận giá trị họ và tên từ người dùng nhập vào bàn phím và in họ tên đó ra màn hình:

Ở ví dụ này tôi sử dụng hàm gets, puts và để dễ dàng hơn với việc thao tác với chuỗi ký tự:

#include <stdio.h>
// Dinh nghia mot ham hoTen co chuc nang nhap va in ra ho ten
void hoTen(){
   // Khai bao hai mang gom 100 ky tu de chua ho,ten
   char ho[100];
   char ten[100];
   //Nhap ho va ten dem
   printf("Nhap ho va ten dem: \n");
   //Ham gets(ho); nhan mot chuoi ky tu o ban phim roi gan vao char ho
   gets(ho);
   //Nhap ten
   printf("Nhap ten: \n");
   //Ham gets(ten); nhan mot chuoi ky tu o ban phim roi gan vao char ten
   gets(ten);
   //Hien thi ho va ten sau khi nguoi dung da nhap vao
   printf("Ho va ten la: %s %s",ho,ten);
   
}
int main () {
   //Goi ham hoTen() de kiem tra ket qua    
   hoTen();
   return 0;
}
Nhap ho va ten dem:

Chu Minh

Nhap ten:

Nam

Ho va ten la: Chu Minh Nam

4.Truyền tham chiếu vào trong hàm

Một tham chiếu được truyền vào hàm chính là việc chuyền một địa chỉ của biến đầu vào vào trong hàm, khi đó việc thực hiện và thay đổi giá trị của biến đầu vào (tham chiếu trong hàm) sẽ ảnh hưởng đến biến ban đầu (bên ngoài hàm).

Để truyền một tham chiếu vào hàm, ta có cú pháp sau:

return_type name( parameter *list) {
   CodeBlock;
   return result;
}

Điều đặc biệt ở việc truyền tham chiếu vào trong hàm trên chúng ta thấy xuất hiện dấu * (dấu sao) trước tên list (hay còn hiểu là có sự xuất hiện của dấu * trước tên biến truyền vào).

Việc thêm dấu * trước tên biến như vậy sẽ được làm rõ hơn trong bài con trỏ (Lập trình C nâng cao), bây giờ bạn đọc chỉ cần thực hiện theo đúng cú pháp, chúng ta sẽ cùng tìm hiểu thêm vấn đề trên ở bài con trỏ.

Trong hàm chính (hàm main) để sử dụng hàm có tham số truyền vào là tham chiếu ta sử dụng cú pháp name(parameter &list)

Một điều đặc biệt nữa ta nhận thấy rằng có sự xuất hiện của dấu & (dấu và) trước tham số truyền vào (hay còn hiểu là dấu & trước biến truyền vào).

Để có cái nhìn tổng quan hơn về việc chuyền tham chiếu vào trong hàm, tôi có một ví dụ minh họa dưới đây:

#include<stdio.h>
void thamChieu(int *a, int *b) {
    *a = *a + 1;
    *b = *b - 1;
}
 
int main() {
    //khai bao a, b co gia tri la 10
    int a = 10;
    int b = 10;
    //hien thi a va b
    printf("a ban dau %d \n", a);
    printf("b ban dau %d \n", b);
    printf("a va b sau khi la gia tri tham chieu duoc truyen vao ham thamChieu() la: \n");
    //truyen a, b la tham chieu vao ham thamChieu()
    thamChieu(&a,&b);
    //ket qua sau khi a, b duoc truyen vao ham thamChieu()
    printf("a = %d \n", a);
    printf("b = %d \n", b);
    
    return 0;
}
a ban dau 10

b ban dau 10

a va b sau khi la gia tri tham chieu duoc truyen vao ham thamChieu() la:

a = 11

b = 9

Nhận xét: Biến a, b ban đầu có giá trị là 10 sau khi truyền tham chiếu a, b vào hàm theo cú pháp thamChieu(&a,&b) thì giá trị của a, b đều thay đổi lần lượt là 11, 9 lý do vì trong hàm thamChieu có sự tính toán của các biến a, b và kết quả của sự tính toán đó được gán bằng chính 2 biến a, b ban đầu.

Nói ngắn ngọn lại ta hiểu truyền tham chiếu vào hàm là việc biến đổi biến số ban đầu mang giá trị theo biến số trong hàm sau khi thực hiện các tác vụ trong hàm đó.