C – Đối Số Biến Thiên (Variable Arguments)

Thỉnh thoảng, bạn có thể gặp một tình huống, là khi bạn muốn có một hàm, mà hàm này có số lượng đối số (argument) biến thiên (không xác định), ví dụ như tham số (parameter), thay vì số lượng tham số được xác định trước. May mắn thay, ngôn ngữ lập trình C đã cung cấp một giải pháp cho tình huống này, và bạn được phép định nghĩa (define) một hàm có thể nhập nhiều tham số có số lượng biến thiên dựa trên nhu cầu của bạn. Ví dụ sau đây cho thấy định nghĩa của một hàm như vậy.

int func(int, ... ) {
   .
   .
   .
}

int main() {
   func(1, 2, 3);
   func(1, 2, 3, 4);
}

Cách định nghĩa hàm có đối số biến thiên

Cần chú ý rằng hàm func() có đối số cuối cùng là dấu ba chấm (…) và đối số trước nó luôn luôn là một int, đối số này thể hiện tổng số lượng đối số được đưa vào hàm. Để sử dụng chức năng này, bạn cần include file header stdarg.h, nó cung cấp những hàm và macro để hiện thực (implement) chức năng của việc biến thiên đối số. Bạn hãy làm theo những bước sau:

  • Định nghĩa (define) một hàm với tham số (parameter) cuối cùng của nó là dấu ba chấm (…) và đối số trước nó luôn là một int sẽ tượng trưng cho số lượng đối số (argument).
  • Tạo một biến kiểu va_list trong định nghĩa hàm. Kiểu này được define trong file header stdarg.h
  • Sử dụng tham số int và macro va_start để khởi tạo biến va_list là một danh sách đối số.
  • Hai macro va_arg và biến va_list được dùng để truy cập mỗi item trong danh sách đối số.
  • Cuối cùng, gọi macro va_end để dọn dẹp bộ nhớ được gán cho biến va_list.

Ví dụ

Bây giờ, chúng ta sẽ làm theo những bước trên và viết một hàm đơn giản có thể lấy tham số với số lượng thay đổi và trả về giá trị trung bình của chúng.

#include <stdio.h>
#include <stdarg.h>

double average(int num,...) {
   va_list valist;
   double sum = 0.0;
   int i;

   /* initialize valist for num number of arguments */
   va_start(valist, num);

   /* access all the arguments assigned to valist */
   for (i = 0; i < num; i++) {
      sum += va_arg(valist, int);
   }

   /* clean memory reserved for valist */
   va_end(valist);

   return sum/num;
}

int main() {
   printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

Khi đoạn code trên được biên dịch và thực thi, nó sẽ cho kết quả như sau. Cần chú ý rằng hàm average() được gọi 2 lần, và mỗi lần gọi thì đối số thứ nhất tượng trưng cho tổng số lượng đối số được truyền vô hàm. Còn dấu ba chấm được sử dụng để truyền các đối số với số lượng tùy ý.

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000

Tìm hiểu thêm về stdarg.h theo chuẩn IEEE 1003.1.

(Tiếp theo)

Icons made by Freepik from www.flaticon.com