2016-12-01 61 views
1

筆者近日瞭解到,有parameter-type-lists可以在C空:如何在C代碼庫中查找使用參數類型列表?

int print(); 

int main() { 
    print("hallo"); // << valid but highly unintuitive 
} 

int print() { 
} 

在此代碼的人可能只是忘了寫print(void)(可能是C++開發者)都是別人提供的參數。編譯不顯示任何警告或錯誤:

$ make test -Wstrict-prototypes -Wimplicit -Wimplicit-function-declaration -Wall 
cc  test.c -o test 

我沒有找到,警告有關空參數類型列表中,只有大約隱函數聲明中的編譯器標誌。

有什麼我可以做的,這有助於我在給定的代碼庫中找到參數類型列表的所有用法?

E.g.

  • letting a C++ compiler compile the C code as C++和解決型問題(C++不允許的參數,如果該聲明不一一列舉)
  • 讓編譯器列表中的所有函數聲明(不知道如果可能的話)和手動搜索空括號
  • grep荷蘭國際集團的參數類型列表中(對我來說太複雜了:))
  • 通過編譯器開關禁用參數類型列表(沒有發現任何)
+2

您無法使用C++編譯器編譯C代碼! C++是一種不同的語言,相同的語法並不意味着相同的語義。 C++是**不是**「C與類」!而參數類型列表正是你**必須使用的正確的C語言。其他所有內容已經過時並且自17年以來已被棄用。不清楚你想完成什麼。 – Olaf

+0

http://stackoverflow.com/a/861556/1668622 – frans

+0

你是對的,但與有效的C++代碼的差異正是我試圖找到的 - 問題是我會發現比預期更多的問題: ) – frans

回答

0

所有你需要的要查找的是()(帶有可選空白),然後是{(帶有可選空白,也許是換行符)。你可以用(void)替換它。

如果你想要一個「工業級」解決方案,你可以使用一個編譯器來發布一些更容易解析的東西,比如GCC-XMLClang

+0

如果有一個例子,這將是一個明確的答案。這是我在問題中列出的第二種和第三種方法。但是因爲到處都可能有空格和換行符,這會導致正則表達式/逃離地獄。 – frans

2

與海灣合作委員會,利用-Wstrict的原型將達到你所期望的:

-Wstrict的原型(C和唯一的目標-C) 警告如果一個函數或聲明沒有指定的定義參數類型。 (如果先進行指定的參數類型的聲明的舊式函數定義允許沒有警告)

你的榜樣,它提供了:

hallo.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes] 
int print() { 
    ^

但是,你必須確保現有代碼中的所有非嚴格函數聲明都得到正確定義;特別是,如果沒有參數函數應該與(無效)被聲明,像這樣:

int print(void); 
+0

如果OP使用GCC,但是不完整,這很好。如果在範圍內沒有函數'print()'的聲明,那麼'-Wstrict-prototypes'沒有什麼值得警告的。 –

+1

但是我會收到'int print(){..}'(沒有void)和'-Wimplicit-function-declaration'' * * *提供完整原型的警告。當我想打電話給'print(「hello」);' – frans

1

你的例子是有效,無論是用C也不在C++。由於您的print()函數不接受任何參數 - 您可以根據函數定義確定任何參數(C2011,6.7.6.3/14) - 使用參數調用它是不合格的,無論是原型在呼叫時可見(C2011,6.5.2.2/6)。如果調用出現在功能定義和任何原型都不可見的範圍內,那麼編譯器可能會接受該代碼,但這不會使其有效或保證它可以工作。

此外,您似乎使用了錯誤的術語,或者您的想法可能是錯誤的。參數類型列表是聲明(和定義)功能,包括函數原型的現代方式:

int my_func(int a, char *b); 
//   ^^^^^^^^^^^^^^----- parameter-type-list 

你應該擺脫那些的,但我覺得你的意思是要識別和修復K & R型函數定義和函數聲明沒有參數類型列表。 (K & R風格的形式語法的術語是「標識符列表」,如果需要,附帶的「聲明列表」。)

至於自動識別K風格聲明的發生,這是一項工作對於C語言解析器來說,最常見的是C編譯器。您的編譯器可能只有您想要的選項。例如,GCC具有選項-Wstrict-prototypes-Wold-style-defintion,它們一起將用信號表示不是原型的功能聲明和R型功能定義。海灣合作委員會還有其他一些可能會讓你感興趣的選項,例如-Wimplicit,-Wtraditional-Wc++-compat

+0

那麼,你的答案聽起來很深刻,所以也許我不明白這一點。我的問題是,編譯器**不接受'void print(){..}'並用參數調用它。也許我的措辭是錯誤的.. – frans

+0

@frans,如果你的編譯器接受帶有參數的函數調用,即使函數定義沒有指定任何參數,那麼在調用點範圍內沒有該函數的原型,或編譯器是越野車。如果你使用GCC,那麼如果你使用'-Wimplicit'(或'-Wall'),它會警告你對未聲明函數的調用。在這種情況下,如果你也使用'-Wstrict-prototypes',那麼GCC將會標記不提供原型的函數聲明。使用這種組合,你的代碼不應該通過GCC而不會引發某種診斷。 –

+1

你真的嘗試過嗎? http://stackoverflow.com/a/13950800/1668622表明它已經過時但是有效。 '-Wstrict-prototypes'發現我在找什麼,所以你的答案*包含*解決方案,但告訴不同的東西.. – frans

相關問題