Trong phần đầu tiên của loạt bài hướng dẫn đang diễn ra này, chúng ta đã thảo luận ngắn gọn về các hàm, bao gồm khai báo và thân hàm. Điều chúng ta chưa thảo luận vào thời điểm đó là nhiều cách gọi hàm. Ở đây, trong hướng dẫn này, chúng ta sẽ thảo luận nhanh về các cách hiện có.
Trong ngôn ngữ C, bạn có thể gọi một hàm theo một số cách: gọi theo giá trị và gọi theo con trỏ hoặc địa chỉ. Hãy thảo luận về cả hai khái niệm này với một số ví dụ dễ hiểu.
Giả sử bạn muốn viết một chương trình hoán đổi hai giá trị. Sau đây là cách bạn có thể thực hiện:
Sau đây là đầu ra của đoạn mã này với các giá trị đã nhập là 5 và 9:
Bây giờ, giả sử yêu cầu là phải có một hàm riêng - chẳng hạn như 'hoán đổi' - thực hiện tất cả các công việc liên quan đến việc hoán đổi và có thể được gọi bất cứ khi nào lập trình viên muốn hoán đổi hai giá trị. Sau đây là mã thực hiện điều này:
Vậy là xong. Một hàm riêng biệt có tên là 'swap' đã được tạo ra để nhận hai giá trị (ban đầu do người dùng nhập và được lưu trong hàm 'main') làm đối số, sau đó hoán đổi chúng và in ra kết quả.
Cách 'swap' được gọi ở đây được gọi là 'gọi theo giá trị'. Lý do là khi thực hiện lệnh gọi, chỉ các giá trị do 'a' và 'b' giữ mới được truyền đến hàm 'swap' làm đối số. Các giá trị này được nhận bởi các đối số 'val1' và 'val2', và chính các biến này là nơi thực hiện quy trình hoán đổi.
Điều này có nghĩa là các biến 'a' và 'b' trong hàm 'main' vẫn giữ các giá trị ban đầu ngay cả sau khi thao tác hoán đổi đã được thực hiện. Nhưng nếu yêu cầu là phải hoán đổi các giá trị của 'a' và 'b' sau khi gọi hàm 'swap' thì sao? Vâng, đây là nơi phương thức 'gọi bằng con trỏ/địa chỉ' xuất hiện.
Về cơ bản, những gì chúng ta làm ở đây là chúng ta truyền địa chỉ của các biến (như 'a' và 'b' trong trường hợp của chúng ta) dưới dạng đối số. Hàm được gọi ('swap' trong trường hợp này) được trang bị để nhận địa chỉ dưới dạng đối số và sau đó quá trình hoán đổi được thực hiện trên các giá trị được giữ tại các địa chỉ này, về cơ bản có nghĩa là các giá trị của biến gốc ('a' và 'b' ở đây) được hoán đổi.
Bây giờ, trong đoạn trước, chúng ta đã nói rằng hàm "được trang bị để nhận địa chỉ dưới dạng đối số". Vâng, bằng "được trang bị", chúng ta muốn nói rằng nó có loại đối số đặc biệt có thể nhận địa chỉ. Các đối số này là các biến loại 'con trỏ'. Chúng ta sẽ thảo luận chi tiết về 'con trỏ' trong hướng dẫn sắp tới, nhưng hiện tại, hãy nhớ rằng các biến con trỏ lưu trữ địa chỉ bộ nhớ dưới dạng giá trị.
Đây là cách một con trỏ đến một số nguyên được khai báo/định nghĩa:
Về cơ bản, x là một biến con trỏ có thể được sử dụng để lưu trữ địa chỉ bộ nhớ của một biến số nguyên. Giả sử 'i' là một biến số nguyên, thì đây là cách bạn có thể khiến 'x' lưu trữ địa chỉ của 'i':
Và bất cứ khi nào bạn muốn truy cập giá trị của 'i' thông qua 'x', bạn hãy viết '*x'. Ví dụ, đây là cách bạn có thể thay đổi giá trị của 'i' thành, chẳng hạn, 10:
Vì vậy, với tất cả những điều này trong đầu, đây là cách bạn có thể gọi 'swap' bằng cách sử dụng phương thức gọi theo địa chỉ hoặc con trỏ:
Vì vậy, lần này, thay vì truyền giá trị của 'a' và 'b' làm đối số, chúng ta đã truyền địa chỉ của các biến này. Trong hàm 'hoán đổi', các địa chỉ được nhận trong hai biến con trỏ ('val1' và 'val2'). Và khi sử dụng hai biến con trỏ, logic sẽ trực tiếp hoán đổi giá trị của 'a' và 'b'.
Đây là đầu ra:
Bài viết này ít nhất sẽ cung cấp cho bạn ý tưởng cơ bản về cách gọi hàm 'gọi theo giá trị' và 'gọi theo địa chỉ/con trỏ', cũng như khi nào có thể sử dụng chúng. Hãy thử các ví dụ mà chúng tôi đã liệt kê ở đây và cho chúng tôi biết trong phần bình luận bên dưới nếu bạn có bất kỳ thắc mắc hoặc câu hỏi nào.
Trong ngôn ngữ C, bạn có thể gọi một hàm theo một số cách: gọi theo giá trị và gọi theo con trỏ hoặc địa chỉ. Hãy thảo luận về cả hai khái niệm này với một số ví dụ dễ hiểu.
Giả sử bạn muốn viết một chương trình hoán đổi hai giá trị. Sau đây là cách bạn có thể thực hiện:
Mã:
#include
int main()
{
int a=0, b=0, c=0;
printf("Nhập hai giá trị số nguyên\n");
scanf("%d %d",&a,&b);
printf("Các giá trị đã nhập là: %d và %d", a,b);
c = a;
a = b;
b = c;
printf("\nCác giá trị đã hoán đổi là: %d và %d", a,b);
return 0;
}
Mã:
Nhập hai giá trị số nguyên
5 9
Các giá trị đã nhập là: 5 và 9
Các giá trị được hoán đổi là: 9 và 5
Mã:
#include
void swap (int val1, int val2)
{
int temp = 0;
temp = val1;
val1 = val2;
val2 = temp;
printf("\nGiá trị được hoán đổi là: %d và %d", val1,val2);
}
int main()
{
int a=0, b=0;
printf("Nhập hai giá trị số nguyên\n");
scanf("%d %d",&a,&b);
printf("Giá trị được nhập là: %d và %d", a,b);
swap(a,b);
return 0;
}
Cách 'swap' được gọi ở đây được gọi là 'gọi theo giá trị'. Lý do là khi thực hiện lệnh gọi, chỉ các giá trị do 'a' và 'b' giữ mới được truyền đến hàm 'swap' làm đối số. Các giá trị này được nhận bởi các đối số 'val1' và 'val2', và chính các biến này là nơi thực hiện quy trình hoán đổi.
Điều này có nghĩa là các biến 'a' và 'b' trong hàm 'main' vẫn giữ các giá trị ban đầu ngay cả sau khi thao tác hoán đổi đã được thực hiện. Nhưng nếu yêu cầu là phải hoán đổi các giá trị của 'a' và 'b' sau khi gọi hàm 'swap' thì sao? Vâng, đây là nơi phương thức 'gọi bằng con trỏ/địa chỉ' xuất hiện.
Về cơ bản, những gì chúng ta làm ở đây là chúng ta truyền địa chỉ của các biến (như 'a' và 'b' trong trường hợp của chúng ta) dưới dạng đối số. Hàm được gọi ('swap' trong trường hợp này) được trang bị để nhận địa chỉ dưới dạng đối số và sau đó quá trình hoán đổi được thực hiện trên các giá trị được giữ tại các địa chỉ này, về cơ bản có nghĩa là các giá trị của biến gốc ('a' và 'b' ở đây) được hoán đổi.
Bây giờ, trong đoạn trước, chúng ta đã nói rằng hàm "được trang bị để nhận địa chỉ dưới dạng đối số". Vâng, bằng "được trang bị", chúng ta muốn nói rằng nó có loại đối số đặc biệt có thể nhận địa chỉ. Các đối số này là các biến loại 'con trỏ'. Chúng ta sẽ thảo luận chi tiết về 'con trỏ' trong hướng dẫn sắp tới, nhưng hiện tại, hãy nhớ rằng các biến con trỏ lưu trữ địa chỉ bộ nhớ dưới dạng giá trị.
Đây là cách một con trỏ đến một số nguyên được khai báo/định nghĩa:
Mã:
int *x;
Mã:
x = &i;
Mã:
*x = 10;
Mã:
#include
void swap (int *val1, int *val2)
{
int temp = 0;
temp = *val1;
*val1 = *val2;
*val2 = temp;
}
int main()
{
int a=0, b=0, c=0;
printf("Nhập hai giá trị số nguyên\n");
scanf("%d %d",&a,&b);
printf("Giá trị đã nhập là: %d và %d", a,b);
swap(&a,&b);
printf("\nGiá trị đã hoán đổi là: %d và %d", a,b);
return 0;
}
Đây là đầu ra:
Mã:
Nhập hai giá trị số nguyên
6 8
Các giá trị đã nhập là: 6 và 8
Các giá trị đã hoán đổi là: 8 và 6