2010-07-30 35 views
17

Giả sử tôi có hàm lấy đối số variadic (...) hoặc va_list được truyền từ một hàm khác như vậy. Logic chính là chính hàm này (chúng ta hãy gọi nó là f1), nhưng tôi muốn chuyển nó va_list sang một hàm khác (hãy gọi nó là f2) sẽ xác định loại đối số tiếp theo, lấy nó bằng cách sử dụng va_arg và chuyển đổi đúng cách lưu trữ nó để người gọi sử dụng.Vượt qua va_list hoặc trỏ đến va_list?

Có đủ để chuyển va_list đến f2 hay là cần thiết để chuyển con trỏ đến va_list. Trừ khi va_list được yêu cầu là loại mảng hoặc lưu trữ dữ liệu vị trí của nó tại vị trí các đối tượng va_list trỏ tới (chứ không phải trong chính đối tượng), tôi không thể biết cách truyền giá trị theo giá trị có thể cho phép hàm gọi (f1) để 'xem' các thay đổi được gọi là chức năng được thực hiện bởi va_arg.

Có ai có thể làm sáng tỏ điều này không? Tôi quan tâm đến những gì tiêu chuẩn yêu cầu, không phải những gì một số thực hiện cụ thể cho phép.

Trả lời

23

Dường như bạn sẽ cần phải chuyển con trỏ đến va_list. Mọi chi tiết, xem phần C99 standard document 7.15.In Đặc biệt, điểm đạn 3 trạng thái:

Đối tượng ap có thể được thông qua như một cuộc tranh cãi để chức năng khác; nếu hàm gọi vĩ mô va_arg với tham số ap, giá trị của ap trong hàm gọi là không xác định và được truyền cho va_end vĩ mô trước khi bất kỳ thông báo thêm cho ap

[nghiêng của tôi]

Edit: Chỉ cần nhận thấy một chú thích trong tiêu chuẩn:

215) được phép để tạo ra một con trỏ đến một va_list và vượt qua con trỏ đến một chức năng, trong đó trường hợp chức năng ban đầu có thể làm cho việc sử dụng đội danh sách ban đầu sau khi các chức năng khác trả

Vì vậy, bạn có thể vượt qua một con trỏ đến va_list và làm va_arg(*va_list_pointer) trong hàm gọi.

+0

Đồng ý với chỉnh sửa cuối cùng của bạn - một con trỏ là con đường để đi (vì OP muốn các thay đổi đối với 'va_list' để chắc chắn có thể nhìn thấy trong chức năng gọi). – caf

+0

@caf: Tôi không nghĩ bạn nên sửa đổi tham chiếu của tôi thành 'vfprintf()' vì có vẻ như những người khác đang phạm sai lầm giống như tôi đã làm và gợi ý người hỏi xem xét các nguyên mẫu hiện có (không thực sự trả lời câu hỏi của mình). – JeremyP

+2

Tôi muốn nói để lại một bình luận và/hoặc bỏ phiếu 'em xuống sau đó - nó có vẻ tốt hơn để có câu trả lời đúng không obfuscated với giả định trước đó, không chính xác ... – caf

2

Theo hiểu biết của tôi, bạn phải chuyển trực tiếp va_list (không phải là con trỏ tới nó). Điều này dường như được hỗ trợ bởi comp.lang.c:.

"Một va_list không phải là bản thân một danh sách đối số biến; nó thực sự sắp xếp của một con trỏ đến một Nghĩa là, một chức năng mà chấp nhận một va_list không phải là bản thân varargs, cũng không phải ngược versa. "

+0

Tôi không nghĩ rằng trích dẫn đó hỗ trợ tranh chấp của bạn. Không có gì về nó không cho phép chuyển một con trỏ tới một 'va_list', và thực sự tiêu chuẩn đó nói rõ ràng điều này được cho phép. – caf

2

Tôi thấy các văn bản khá mơ hồ về câu hỏi này. Cách đơn giản nhất có lẽ là xem xét tiêu chuẩn cách các chức năng được xác định trước với va_list có nghĩa vụ phải nhận được nó, ví dụ: vsnprintf. Và điều này rõ ràng bởi giá trị chứ không phải bằng tham chiếu.

+1

Các chức năng tiêu chuẩn không có ý định được gọi theo cách OP muốn - sau khi chúng được gọi, 'va_list' không còn có thể được sử dụng nữa và chỉ được chuyển tới' va_end() '. – caf

+0

Thật vậy, tôi là OP và tôi đồng ý với quán cà phê trên cái này. JeremyP là người duy nhất dường như đã trích dẫn bất kỳ bằng chứng nào và tiêu chuẩn là khá rõ ràng rằng bạn phải vượt qua một con trỏ cho ngữ nghĩa tôi muốn. –

0

Chức năng trong tiêu chuẩn C thư viện qua va_list yếu tố bản thân (man 3 vprintf):

#include <stdarg.h> 

    int vprintf(const char *format, va_list ap); 
    int vfprintf(FILE *stream, const char *format, va_list ap); 
    int vsprintf(char *str, const char *format, va_list ap); 
    int vsnprintf(char *str, size_t size, const char *format, va_list ap); 
+1

Không có chức năng nào trong số này được dự định được gọi theo cách mà OP muốn - sau khi các hàm này được gọi, 'va_list' không còn được sử dụng nữa và chỉ được chuyển tới' va_end() '. – caf

0

Đi qua một con trỏ để va_list hoạt động tốt trong hệ thống 32 bit. Bạn thậm chí có thể lấy một tham số một thời gian trong tiểu thường trình. Nhưng nó dường như không hoạt động trong hệ thống 64 bit, sẽ tạo ra một lỗi phân đoạn tại va_arg().

Các vấn đề liên quan