2011-01-12 17 views

Trả lời

4

Đây là C99 standard; các loại "tự quảng cáo" là những loại quảng bá cho chính mình khi các quảng cáo đối số mặc định (§6.5.2.2 khoản 6, tham chiếu các chương trình khuyến mãi số nguyên được mô tả trong §6.3.1.1) được áp dụng.

Đọc của tôi về định nghĩa va_arg (§7.15.1.1) là giới hạn này được ngụ ý theo tiêu chuẩn. Phần liên quan là tại đoạn 2:

[...] hoặc nếu loại không tương thích với các loại đối số tiếp theo thực tế (như đề bạt theo đến chương trình khuyến mãi đối số mặc định) [... ]

khá rõ ràng về loại đối số tiếp theo thực sự được quảng cáo, nhưng tôi đọc là không nói bất cứ điều gì về loại đang được quảng cáo. (Tôi nghĩ rằng mệnh đề "(như đã được quảng cáo ...)" chỉ là lời nhắc rằng các quảng cáo đối số mặc định được thực hiện trên các đối số sau khi hàm varargs được gọi.)

Mục này trong danh sách các hành vi chưa xác định trong § k.2 hỗ trợ đọc này:

- các vĩ mô va_arg được gọi khi không có tranh luận tiếp theo thực tế, hoặc với một loại quy định đó không phải là tương thích với các loại bạt của thực tế số tiếp theo, với một số ngoại lệ (7.15.1.1).

(mặc dù có, tôi biết, Phụ lục J "thông tin" thay vì "quy phạm" ...).

Trong trường hợp đó: va_arg(ap, float) (ví dụ) không thể có giá trị - loại trong trường hợp đó là float, nhưng kiểu thúc đẩy của cuộc tranh luận tiếp theo thực tế không thể nào được float (một cuộc tranh luận float sẽ được thăng double).

+0

Có lý do cụ thể nào cho hạn chế này không? Có lẽ một cái gì đó để làm với 'va_arg' implemetation? –

+1

@crypto: Tôi nghi ngờ Zack đúng (xem phản ứng của anh ấy với Jens); không có cách nào rõ ràng để tìm ra quảng cáo đối số mặc định của một kiểu đã cho mà không có sự trợ giúp đặc biệt từ trình biên dịch, vì vậy điều này cho phép thực hiện 'va_arg (ap, type)' hoạt động mà không cần trợ giúp. (ví dụ, giữ một con trỏ byte đến đối số hiện tại trên ngăn xếp trong 'ap'; sau đó' va_arg' có thể là một số macro ghê tởm di chuyển đến đối số tiếp theo bằng cách truyền nó thành 'type *', tăng con trỏ 'type *', và truyền trở lại con trỏ byte.) –

2

Điều này có vẻ là một hạn chế glibc, tiêu chuẩn C không có điều đó.

Ý tưởng đằng sau này là các loại nguyên đã cái gọi là "chuyển đổi cấp bậc" nhỏ hơn int sẽ được tự động thăng signed hoặc unsignedint. Một hàm va_arg sau đó tìm ra một đối số rộng hơn như vậy. Trước tiên, macro va_arg phải đọc đối số rộng hơn loại int và sau đó truyền trở lại loại ban đầu.

(Tương tự giữ cho float w.r.t để double.)

Đối với các lập trình viên không biết điều này có thể có kết quả đáng ngạc nhiên, vì vậy tôi đồng ý với ý tưởng rằng điều này cần phải tránh. Mô tả bạn đang trích dẫn dường như ngụ ý rằng nó được áp dụng để không sử dụng một loại nhỏ. Điều này là không có thật và như tôi đã nói không phù hợp với tiêu chuẩn. Mặt khác, nếu bạn viết mã như họ đề nghị bạn sẽ không bao giờ có một vấn đề di động với điều đó bởi vì đây là một hạn chế và không phải là một phần mở rộng.

+2

Theo hiểu biết tốt nhất của tôi Matthew là chính xác và bạn sai; hạn chế này * là * trong C99 ít nhất. Nếu bạn nghĩ về nó, nó sẽ rất, rất khó - tôi sẽ không thề với _impossible_, nhưng tiêu chuẩn C nói chung tránh đặt các yêu cầu _difficult_ đơn thuần chỉ để thực hiện - để thực hiện "truyền thống" của 'va_arg' (một trong đó không mở rộng đến một trình biên dịch nội tại) mà không có hạn chế này, cho rằng xúc tiến đối số xảy ra trong người gọi. – zwol

+0

@Zack: cho phép nói từ ngữ ít nhất là mơ hồ, phạm vi của "được quảng bá ..." không rõ ràng. Nhưng tôi không đồng ý với bạn rằng việc cho phép các loại hẹp đặt * nhiều * gánh nặng cho việc thực hiện. Họ chỉ cần phải kiểm tra các loại hẹp, đọc một đối số của loại được quảng cáo (việc triển khai phải biết cách tìm loại đó, dù sao đi nữa) và đưa giá trị trở lại loại hẹp. –

+2

Đó sẽ là một điều dễ dàng để làm * từ trình biên dịch nội tại *. Việc triển khai truyền thống của 'va_arg' không có quyền truy cập vào bất kỳ tiện ích nào như vậy; nó làm mọi thứ với các biểu thức ngôn ngữ cốt lõi (về mặt kỹ thuật không xác định). Vì C không bao gồm bất kỳ cách nào để thực hiện lập trình meta trên các loại, tôi không nghĩ rằng bạn có thể "tìm một đối số của loại được quảng bá và truyền trở lại loại hẹp" chỉ sử dụng các biểu thức ngôn ngữ chính. – zwol

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