2009-06-15 63 views
13

這裏是一個小的一段代碼:如何使用GCC屬性'格式'?

#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; 
} 

我與GCC 4.0編譯它,在Mac OS X Leopard中運行的Xcode。
-Wformat和-Wmissing-format-attribute已啓用。
該代碼給出了第9行(調用vprintf)一個警告,提示MyPrintf可以使用「格式」屬性:

功能可能是「printf」式的格式屬性的備選

所以我添加的屬性這樣(不知道這是正確的):

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

先前警告消失,同樣的警告現在出現在第16行(CA從011到MyPrintf),這表明MyVariadicPrintf可以使用「格式」屬性。
所以我添加的屬性這樣(很肯定這是對這段時間):

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

現在我得到的第22行預期的警告(來電MyVariadicPrintf):

太少格式參數

  1. 我這樣做是正確的嗎?
  2. 我注意到,在MyPrintf聲明中,如果我刪除屬性部分,我仍然會在第22行得到想要的警告。我還注意到,在該屬性部分中,將索引從1更改爲2將不會給出警告或錯誤。哪一個是正確的,這個函數的屬性的目標是什麼?
  3. 如果我添加以下函數MyVariadicPrintfT並將其調用(專用於char),我會收到警告,建議在此函數中使用'format'屬性。我認爲這是不可能的,因爲format參數依賴於模板類型。我對嗎?

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

最新的GNU文檔可以在gnu.org找到。
警告選項在section 3.8(查找「-Wmissing-format-attribute」)。
函數屬性在section 6.30(查找「格式(原型,字符串索引,首先檢查)」)。

謝謝。

回答

10

該文檔有您需要的答案。特別是:

  1. 您已發佈的一個是正確的(format(printf, 1, 0))。 1,因爲格式字符串是參數1,0,因爲沒有可變參數需要檢查。
+1

在MyVariadicPrintf中,我明白編譯器會檢查從位置2開始的參數的數量和類型,而不是位置1處的字符串。但是在MyPrintf的情況下,編譯器檢查了什麼? – Guillaume 2009-06-16 15:10:54

3

看看GCC docs on gnu.org。至於最後一個問題,我的猜測是MyPrintf不是一個模板函數,唯一可用的定義需要char const*作爲第一個參數,所以感覺安全的建議。