2010-10-05 2 views
6

Khi sử dụng va_start(), va_arg() và va_end() để đọc các tham số được truyền cho phương thức, có cách tính số lượng đối số không?Đếm số tham số trong phương thức đối số biến C gọi

Theo man page nếu bạn gọi va_arg() quá nhiều lần bạn nhận được "lỗi ngẫu nhiên":

Nếu không có số tiếp theo, hoặc nếu loại không tương thích với các loại của đối số tiếp theo thực tế (như được quảng cáo theo các quảng cáo đối số mặc định ), các lỗi ngẫu nhiên sẽ xảy ra.

+0

http://groups.google.com/group/comp.std.c/browse_frm/ thread/77ee8c8f92e4a3fb – Nyan

Trả lời

11

Không. Chức năng Đối số biến (chẳng hạn như printf), phải "biết" khi dừng tìm thêm đối số.

printf biết theo số lượng %d, %s và các ký hiệu khác trong chuỗi định dạng của nó.

chức năng

khác đôi khi sử dụng giá trị Sentinel:

sumValues(1, 3, 5, 7, 6, 9, -1); // will add numbers until it encounters a -1 

chức năng khác có thể có số lượng các thông số được nêu lên phía trước:

AddNames(4, "Bill", "Alice", "Mike", "Tom"); 
5

Có hai cách để biết có bao nhiêu đối số được thông qua. Đầu tiên, bạn có thể có một trong các tham số hàm cho bạn biết (ví dụ như printf). Cách khác là để có một giá trị sentinel ở cuối danh sách của bạn - ví dụ, bạn có thể dừng lại ở một đối số NULL.

Bạn có thể sử dụng va_copy nếu bạn chọn phương pháp thứ hai, nhưng vẫn muốn đếm các tham số trước khi quyết định phải làm gì với chúng.

8

Đây là một thủ thuật khá lạ lùng mà cho phép bạn xây dựng những gì mà bạn muốn sử dụng các macro variadic C99 của:

PP_NARG()
Trả về số đối số chứa trong __VA_ARGS__

Bạn có thể sử dụng này để viết một macro gói hàm thực sự của bạn để thêm số đếm vào trước đối số của hàm thực.

Xem thêm this question. Tuy nhiên có lẽ cách tiếp cận cổ điển vẫn còn hợp lý hơn trong một hoặc ba năm!


Mã, do đó câu trả lời này là hữu ích ngay cả khi không lưu trữ Usenet ...

/* The PP_NARG macro returns the number of arguments that have been 
    * passed to it. 
    */ 

#define PP_NARG(...) \ 
     PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) 
#define PP_NARG_(...) \ 
     PP_ARG_N(__VA_ARGS__) 
#define PP_ARG_N(\ 
      _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
     _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 
     _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 
     _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 
     _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 
     _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 
     _61,_62,_63,N,...) N 
#define PP_RSEQ_N() \ 
     63,62,61,60,     \ 
     59,58,57,56,55,54,53,52,51,50, \ 
     49,48,47,46,45,44,43,42,41,40, \ 
     39,38,37,36,35,34,33,32,31,30, \ 
     29,28,27,26,25,24,23,22,21,20, \ 
     19,18,17,16,15,14,13,12,11,10, \ 
     9,8,7,6,5,4,3,2,1,0 
+0

Tôi nên nói điều này thật đáng yêu :-) Phát hiện thú vị! – jweyrich

+0

Chính xác những gì tôi định nói! – Nyan

+0

P99 sẽ có một bộ macro lấy cảm hứng từ đó và đó có thể chính xác là những gì bạn cần. Rất tiếc, bản phát hành sẽ chỉ diễn ra trong một vài tuần, nhưng nếu bạn muốn xem tài liệu: http://p99.gforge.inria.fr/p99-html/group__variadic.html –