Vấn đề với C variadics là họ đang thực sự bắt vít vào sau đó, không thực sự được thiết kế sang ngôn ngữ. Vấn đề chính là các tham số variadic là ẩn danh, chúng không có tay cầm, không có mã định danh. Điều này dẫn đến các macro VA khó sử dụng để tạo tham chiếu đến các tham số không có tên. Nó cũng dẫn đến sự cần thiết phải nói cho các macro đó khi danh sách variadic bắt đầu và loại tham số nào được mong đợi.
Tất cả thông tin này thực sự phải được mã hóa theo cú pháp thích hợp trong chính ngôn ngữ đó.
Ví dụ, người ta có thể mở rộng cú pháp C hiện với các thông số chính thức sau khi lược, như vậy
void foo (... int counter, float arglist);
Theo quy ước, tham số đầu tiên có thể cho số lượng đối số và thứ hai cho danh sách đối số. Trong phần thân hàm, danh sách có thể được xử lý cú pháp như một mảng.
Với quy ước như vậy, các tham số variadic sẽ không còn ẩn danh nữa. Trong cơ quan chức năng, bộ đếm có thể được tham chiếu như bất kỳ thông số khác và các yếu tố danh sách có thể được tham chiếu như thể chúng là các phần tử mảng của một tham số mảng, như vậy
void foo (... int counter, float arglist) {
unsigned i;
for (i=0; i<counter; i++) {
printf("list[%i] = %f\n", i, arglist[i]);
}
}
Với tính năng như vậy được xây dựng vào ngôn ngữ riêng của mình , mỗi tham chiếu đến arglist[i]
sau đó sẽ được dịch sang các địa chỉ tương ứng trên khung ngăn xếp. Sẽ không cần phải làm điều này thông qua các macro.
Hơn nữa, số đối số sẽ tự động được trình biên dịch chèn vào, làm giảm thêm cơ hội lỗi.
Một cuộc gọi đến
foo(1.23, 4.56, 7.89);
sẽ được biên dịch như thể nó đã được viết
foo(3, 1.23, 4.56, 7.89);
Trong cơ quan chức năng, bất cứ quyền truy cập vào một yếu tố vượt quá con số thực tế của các đối số thực sự trôi qua có thể là kiểm tra tại thời gian chạy và gây ra một lỗi thời gian biên dịch, do đó tăng cường an toàn rất nhiều.
Cuối cùng nhưng không kém phần quan trọng, tất cả các tham số variadic được nhập và có thể được kiểm tra kiểu tại thời gian biên dịch giống như các tham số không-variadic được chọn.
Trong một số trường hợp sử dụng, tất nhiên là mong muốn có các loại xen kẽ, chẳng hạn như khi viết một hàm để lưu trữ khóa và giá trị trong bộ sưu tập. Điều này cũng có thể được cung cấp chỉ đơn giản bằng cách cho phép nhiều tham số chính thức sau khi lược, như vậy
void store (collection dict, ... int counter, key_t key, val_t value);
Chức năng này sau đó có thể được gọi là
store(dict, key1, val1, key2, val2, key3, val3);
nhưng sẽ được biên dịch như thể nó đã được viết
store(dict, 3, key1, val1, key2, val2, key3, val3);
Các loại tham số thực tế sẽ được kiểm tra thời gian biên dịch theo các thông số chính thức của biến thể variadic tương ứng.
Trong cơ thể của hàm quầy một lần nữa sẽ được tham chiếu bởi định danh, khóa và giá trị của nó sẽ được tham chiếu như thể chúng là mảng,
key[i]
đề cập đến quan trọng của cặp khoá/giá trị thứ i value[i]
đề cập đến giá trị của cặp giá trị thứ i
và các tham chiếu này sẽ được biên soạn đến địa chỉ tương ứng của chúng trên khung ngăn xếp.
Không ai trong số này thực sự khó thực hiện, cũng như chưa từng có. Tuy nhiên, triết lý thiết kế của C chỉ đơn giản là không có lợi cho các tính năng như vậy.
Nếu không có một mạo hiểm trình biên dịch C implementor (hoặc C Preprocessor implementor) đi đầu để thực hiện điều này hoặc một chương trình tương tự nó là không bao giờ chúng ta sẽ thấy bất cứ điều gì của loại hình này trong C.
Vấn đề là folks người quan tâm đến an toàn loại và sẵn sàng đưa vào công việc xây dựng trình biên dịch riêng của họ thường đi đến kết luận rằng ngôn ngữ C vượt quá khả năng cứu hộ và người ta cũng có thể bắt đầu lại bằng ngôn ngữ được thiết kế tốt hơn để bắt đầu.
Tôi đã ở đó, cuối cùng quyết định từ bỏ nỗ lực, sau đó thực hiện một trong các ngôn ngữ của Wirth và thêm các loại variadics an toàn vào thay thế. Tôi có kể từ khi chạy vào những người khác, những người đã nói với tôi về những nỗ lực của họ. Loại variadics an toàn loại trong C dường như sẵn sàng để giữ khó nắm bắt.
Nếu tất cả các loại cần phải cùng loại, bạn có xem xét việc chỉ chuyển một mảng trong số đó không? –
Không có mảng gốc trong C89. Bạn không thể vượt qua ví dụ, 'f ({1,2,3,0})' với trình biên dịch MS C. – mikebloch
bạn muốn một cái gì đó mà làm việc với gcc hoặc MS C? Vui lòng gắn thẻ một cách thích hợp. Với C99 có các giải pháp an toàn. –