Truyền
bằng tham chiếu
Khi các
đối số được truyền bằng giá trị, các giá trị của đối số của hàm đang gọi không
bị thay đổi. Tuy nhiên, có thể có trường hợp, ở đó giá trị của các đối số phải
được thay đổi. Trong những trường hợp như vậy, truyền bằng tham chiếu được
dùng. Truyền bằng tham chiếu, hàm được phép truy xuất đến vùng bộ nhớ thực
của các đối số và vì vậy có thể thay đổi giá trị của các đối số của hàm gọi.
Ví dụ,
xét một hàm, hàm này nhận hai đối số, hoán vị giá trị của chúng và trả về các
giá trị của chúng. Nếu một chương trình giống như chương trình dưới đây được viết
để giải quyết mục đích này, thì sẽ không bao giờ thực hiện được.
#include <stdio.h>
int main()
{
int x, y;
x = 15; y = 20;
printf(“x = %d, y = %d\n”, x,
y);
swap(x, y);
printf(“\nAfter interchanging
x = %d, y = %d\n”, x, y);
}
void swap(int u, int v)
{
int temp;
temp = u;
u = v;
v = temp;
return;
}
Kết quả
của chương trình trên như sau:
x = 15, y = 20
After interchanging x = 15, y = 20
Hàm swap()
hoán vị các giá trị của u và v, nhưng các giá trị này không được truyền trở về
hàm main(). Điều này là bởi vì các biến u và v trong swap()
là khác với các biến u và v được dùng trong main(). Truyền
bằng tham chiếu có thể được sử dụng trong trường hợp này để đạt được kết quả
mong muốn, bởi vì nó sẽ thay đổi các giá trị của các đối số thực. Các con trỏ
được dùng khi thực hiện truyền bằng tham chiếu.
Các con
trỏ được truyền đến một hàm như là các đối số để cho phép hàm được gọi của
chương trình truy xuất các biến mà phạm
vi của nó không vượt ra khỏi hàm gọi. Khi một con trỏ được truyền đến một hàm,
địa chỉ của dữ liệu được truyền đến hàm nên hàm có thể tự do truy xuất nội dung
của địa chỉ đó. Các hàm gọi nhận ra bất kỳ thay đổi trong nội dung của địa chỉ.
Theo cách này, đối số hàm cho phép dữ liệu được thay đổi trong hàm gọi, cho
phép truyền dữ liệu hai chiều giữa hàm gọi và hàm được gọi. Khi các đối số của
hàm là các con trỏ hoặc mảng, truyền bằng tham chiếu được tạo ra đối nghịch với
cách truyền bằng giá trị.
Các đối
số hình thức của một hàm là các con trỏ thì phải có một dấu * phía trước, giống
như sự khai báo biến con trỏ, để xác định chúng là các con trỏ. Các đối số thực
kiểu con trỏ trong lời gọi hàm có thể được khai báo là một biến con trỏ hoặc một
biến được tham chiếu đến (&var).
Ví dụ
getstr(char *ptr_str, int *ptr_int)
đối số ptr_str
trỏ đến kiểu char và ptr_int trỏ đến kiểu int. Hàm có thể
được gọi bằng câu lệnh.
getstr(pstr, &var)
ở đó pstr
được khai báo là một con trỏ và địa chỉ của biến var được truyền.
Gán giá trị thông qua.
*ptr_int = var;
Hàm bây
giờ có thể gán các giá trị đến biến var trong hàm gọi, cho phép truyền
theo hai chiều đến và từ hàm.
char *pstr;
Quan
sát ví dụ sau của hàm swap(). Bài toán này sẽ giải quyết được khi con trỏ
được truyền thay vì dùng biến. Mã lệnh tương tự như sau:
#include <stdio.h>
void main()
{
int x, y, *px, *py;
/* Storing address of x in px
*/
px = &x;
/* Storing address of y in py
*/
py = &y;
x = 15; y = 20;
printf(“x = %d, y = %d \n”,
x, y);
swap (px, py);
/* Passing addresses of x and
y */
printf(“\n After
interchanging x = %d, y = %d\n”, x, y);
}
void swap(int *u, int *v)
/* Accept
the values of px and py into u and v */
{
int temp;
temp = *u;
*u = *v;
*v = temp;
return;
}
Kết quả
của chương trình trên như sau:
x = 15, y = 20
After interchanging x = 20, y = 15
Hai biến
kiểu con trỏ px và py được khai báo, và địa chỉ của biến x
và y được gán đến chúng. Sau đó các biến con trỏ được truyền đến hàm swap(),
hàm này hoán vị các giá trị lưu trong x và y thông qua các con trỏ.
Sự lồng
nhau của lời gọi hàm
Lời gọi
một hàm từ một hàm khác được gọi là sự lồng nhau của lời gọi hàm.
Một chương trình kiểm tra một chuỗi có phải là chuỗi đọc xuôi - đọc ngược như
nhau hay không, là một ví dụ cho các lời gọi hàm lồng nhau. Từ đọc xuôi - ngược
giống nhau là một chuỗi các ký tự đối xứng. Xem đoạn mã lệnh theo sau đây:
void main()
{
.
.
palindrome();
.
.
}
palindrome()
{
.
.
getstr();
reverse();
cmp();
.
.
}
Trong
chương trình trên, hàm main() gọi hàm palindrome(). Hàm palindrome()
gọi đến ba hàm khác getstr(), reverse() và cmp(). Hàm getstr()
để nhận một chuỗi ký tự từ người dùng, hàm reverse() đảo ngược chuỗi và
hàm cmp() so sánh chuỗi được nhập vào và chuỗi đã được đảo.
Vì main()
gọi palindrome(), hàm palindrome() lần lượt gọi các hàm getstr(),
reverse() và cmp(), các lời
gọi hàm này được gọi là được lồng bên trong palindrome().
Sự lồng
nhau của các lời gọi hàm như trên là được phép, trong khi định nghĩa một hàm
bên trong một hàm khác là không được chấp nhận trong C.
Đăng nhận xét