2009-06-15 33 views
13

Đây là một mảnh nhỏ của mã:Cách sử dụng thuộc tính GCC 'định dạng'?

#include <stdio.h> 
#include <stdarg.h> 

void MyPrintf(char const* format, va_list args); 
void MyVariadicPrintf(char const* format, ...); 

void MyPrintf(char const* format, va_list args) 
{ 
    vprintf(format, args); 
} 

void MyVariadicPrintf(char const* format, ...) 
{ 
    va_list args; 
    va_start(args, format); 
    MyPrintf(format, args); 
    va_end(args); 
} 

int main(int, char*) 
{ 
    MyVariadicPrintf("%s" /* missing 2nd argument */); 

    return 0; 
} 

Tôi biên dịch nó với GCC 4.0, chạy Xcode trên Mac OS X Leopard.
-Wformat và -Wmissing-format-attribute được bật.
Mã này đưa ra một cảnh báo trên đường 9 (gọi để vprintf), cho thấy rằng MyPrintf có thể sử dụng 'định dạng' thuộc tính:

chức năng có thể là khả năng ứng cử viên cho 'printf' thuộc tính định dạng

Vì vậy, tôi thêm thuộc tính theo cách này (không chắc chắn nếu điều này là đúng):

void MyPrintf(char const* format, va_list args) __attribute__((format(printf, 1, 0))); 

Cảnh báo trước đó biến mất và cảnh báo tương tự hiện xuất hiện trên dòng 16 (ca sẽ đến MyPrintf), gợi ý rằng MyVariadicPrintf có thể sử dụng thuộc tính 'định dạng'.
Vì vậy, tôi thêm các thuộc tính theo cách này (khá chắc chắn điều này là đúng thời điểm này):

void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2))); 

Và bây giờ tôi nhận được cảnh báo dự kiến ​​trên dòng 22 (gọi để MyVariadicPrintf):

quá ít đối số cho định dạng

  1. Tôi có làm điều này đúng không?
  2. Tôi nhận thấy rằng trên khai báo MyPrintf, nếu tôi xóa phần thuộc tính, tôi vẫn sẽ nhận được cảnh báo mong muốn trên dòng 22. Tôi cũng nhận thấy rằng trong phần thuộc tính này, việc thay đổi chỉ mục từ 1 đến 2 sẽ không đưa ra bất kỳ cảnh báo hoặc lỗi. Cái nào là đúng và mục đích của thuộc tính trên hàm này là gì?
  3. Nếu tôi thêm chức năng sau MyVariadicPrintfT và gọi nó (chuyên biệt với char), tôi sẽ nhận được cảnh báo đề xuất sử dụng thuộc tính 'định dạng' trên chức năng này. Tôi nghĩ rằng nó là không thể bởi vì đối số format phụ thuộc vào loại templated. Tôi có đúng không?

    template<typename Type> 
    void MyVariadicPrintfT(Type const* format, ...) 
    { 
        va_list args; 
        va_start(args, format); 
        MyPrintf(format, args); 
        va_end(args); 
    } 
    

Các tài liệu gnu mới nhất có thể được tìm thấy tại gnu.org.
Tùy chọn cảnh báo có trong section 3.8 (tìm kiếm "-Wmissing-format-attribute").
Thuộc tính chức năng nằm trong section 6.30 (tìm "định dạng (kiểu mẫu, chuỗi chỉ mục, kiểm tra đầu tiên)").

Cảm ơn.

Trả lời

10

Tài liệu có câu trả lời bạn cần.Đặc biệt:

  1. Một bạn đã đăng là chính xác (format(printf, 1, 0)). 1 vì chuỗi định dạng là tham số 1, 0 vì không có đối số variadic nào được chọn.
+1

Trong MyVariadicPrintf, tôi hiểu rằng trình biên dịch sẽ kiểm tra số và loại đối số bắt đầu tại vị trí 2 so với chuỗi tại vị trí 1. Nhưng trong trường hợp MyPrintf, trình biên dịch kiểm tra cái gì? – Guillaume

+1

Trong trường hợp MyPrintf, nó sẽ chỉ kiểm tra tính hợp lệ của chuỗi định dạng (ví dụ: nó không giống như "% _%") – jpalecek

+0

Ok, cảm ơn rất nhiều! – Guillaume

3

Hãy xem qua số GCC docs on gnu.org. Đối với câu hỏi cuối cùng, tôi đoán rằng MyPrintf không phải là một chức năng mẫu và định nghĩa duy nhất có sẵn mất char const* làm đối số đầu tiên để nó cảm thấy an toàn khi đưa ra đề xuất.

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