Gọi hàm
Hàm được gọi khi tên của nó được đề cập trong một biểu thức. Sau tên hàm, cần có một cặp dấu ngoặc đơn, trong đó các đối số tương ứng với các tham số của hàm (nếu có danh sách tham số trong định nghĩa của nó) được chỉ định, phân tách bằng dấu phẩy.
Một lát nữa, chúng ta sẽ xem xét kiểu con trỏ hàm, kiểu này cho phép tạo các biến trỏ đến một hàm với các đặc điểm cụ thể, và sau đó gọi nó không phải bằng tên, mà thông qua biến này.
Tiếp tục ví dụ với hàm Fibo
, hãy gọi nó từ hàm OnStart
. Để làm điều này, chúng ta tạo một biến f
để lưu trữ số kết quả và trong biểu thức khởi tạo của nó, chúng ta chỉ định tên hàm Fibo
cùng với một số nguyên (ví dụ, 10) làm đối số, trong dấu ngoặc đơn.
void OnStart()
{
int f = Fibo(10);
Print(f); // 89
}
2
3
4
5
Chúng ta không bắt buộc phải tạo một biến để nhận giá trị từ hàm. Thay vào đó, bạn có thể gọi hàm trực tiếp từ một biểu thức, chẳng hạn như "2*Fibo(10)" hoặc "Print(Fibo(10))". Khi đó, giá trị của nó sẽ được thay thế vào biểu thức tại vị trí gọi. Ở đây, biến phụ f
được đưa vào để thực hiện việc gọi và trả về giá trị trong một câu lệnh riêng biệt.
Quá trình gọi bao gồm các bước sau:
- Thực thi chuỗi câu lệnh của hàm gọi (
OnStart
) bị tạm dừng; - Giá trị của đối số được đưa vào tham số đầu vào
n
của hàm được gọi (Fibo
); - Bắt đầu thực thi các câu lệnh của nó;
- Khi hoàn tất hoàn toàn, nó gửi kết quả trở lại (nhớ câu lệnh
return
bên trong); - Kết quả được ghi vào biến
f
; và - Sau đó, việc thực thi hàm
OnStart
tiếp tục, tức là số được in ra nhật ký (Print
).
Đối với mỗi lần gọi hàm, trình biên dịch tạo mã nhị phân phụ trợ (lập trình viên không cần lo lắng về điều này). Ý tưởng của mã này là trước khi gọi hàm, nó đẩy vị trí hiện tại trong chương trình vào ngăn xếp (stack), và sau khi cuộc gọi hoàn tất, nó lấy lại vị trí đó và sử dụng nó để quay lại các câu lệnh tiếp theo sau cuộc gọi hàm. Khi một hàm gọi hàm khác, hàm đó gọi thêm một hàm nữa, hàm thứ hai gọi hàm thứ ba, v.v., các địa chỉ trả về của các chuyển tiếp trong suốt hệ thống phân cấp của các hàm được gọi sẽ được tích lũy trên ngăn xếp (do đó có tên là stack). Khi các cuộc gọi hàm lồng nhau được xử lý, ngăn xếp sẽ được xóa theo thứ tự ngược lại. Lưu ý rằng ngăn xếp cũng cấp phát bộ nhớ cho các biến cục bộ của mỗi hàm.