Có một vấn đề nổi tiếng với các đối số trống cho các macro biến đổi trong C99.
thí dụ:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
Việc sử dụng BAR()
ở trên thực sự không chính xác theo tiêu chuẩn C99, vì nó sẽ mở rộng sang:
printf("this breaks!",);
Lưu ý dấu phẩy - không khả thi.
Một số trình biên dịch (ví dụ: Visual Studio 2010) sẽ lặng lẽ loại bỏ dấu phẩy đó cho bạn. Các trình biên dịch khác (ví dụ: GCC) hỗ trợ đặt ##
trước __VA_ARGS__
, như vậy:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Nhưng có một cách tuân thủ tiêu chuẩn để có được hành vi này? Có lẽ sử dụng nhiều macro?
Ngay bây giờ, ##
phiên bản có vẻ được hỗ trợ khá tốt (ít nhất là trên nền tảng của tôi), nhưng tôi thực sự muốn sử dụng một giải pháp tuân thủ tiêu chuẩn.
Pre-emptive: Tôi biết tôi chỉ có thể viết một hàm nhỏ. Tôi đang cố gắng làm điều này bằng cách sử dụng macro.
Chỉnh sửa : Đây là một ví dụ (mặc dù đơn giản) về lý do tại sao tôi muốn sử dụng BAR ():
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
Điều này tự động thêm một dòng mới vào các báo cáo ghi nhật ký BAR () của tôi, giả sử fmt
luôn luôn là một chuỗi C được trích dẫn kép. Nó KHÔNG in dòng mới dưới dạng printf () riêng biệt, thuận lợi nếu việc ghi nhật ký được đệm dòng và đến từ nhiều nguồn không đồng bộ.
__VA_OPT__
từ khóa. Điều này đã được "thông qua" bởi C ++, vì vậy tôi hy vọng C sẽ làm theo. (không biết điều đó có nghĩa là nó được theo dõi nhanh vào C ++ 17 hay nếu nó được đặt cho C ++ 20)
BAR
thay vìFOO
ở nơi đầu tiên?