閱讀385 返回首頁    go 阿裏雲 go 技術社區[雲棲]


不常見但是很有用的 GCC 命令行選項(二)

gcc 編譯器提供了幾乎數不清的命令行選項列表。當然,沒有人會使用過或者精通它所有的命令行選項,但是有一些命令行選項是每一個 gcc 用戶都應該知道的 - 即使不是必須知道。它們中有一些很常用,其他一些不太常用,但不常用並不意味著它們的用處沒前者大。

在這個係列的文章中,我們集中於一些不常用但是很有用的 gcc 命令行選項,在第一節已經講到幾個這樣的命令行選項。

不知道你是否能夠回想起,在這個係列教程的第一部分的開始,我簡要的提到了開發者們通常用來生成警告的 -Wall 選項,並不包括一些特殊的警告。如果你不了解這些特殊警告,並且不知道如何生成它們,不用擔心,我將在這篇文章中詳細講解關於它們所有的細節。

除此以外,這篇文章也將涉及與浮點值相關的 gcc 警告選項,以及在 gcc 命令行選項列表變得很大的時候如何更好的管理它們。

在繼續之前,請記住,這個教程中的所有例子、命令和指令都已在 Ubuntu 16.04 LTS 操作係統和 gcc 5.4.0 上測試過。

生成 -Wall 選項不包括的警告

盡管 gcc 編譯器的 -Wall 選項涵蓋了絕大多數警告標記,依然有一些警告不能生成。為了生成它們,請使用 -Wextra 選項。

比如,下麵的代碼:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int i=0;
  6. /* ...
  7. some code here
  8. ...
  9. */
  10. if(i);
  11. return 1;
  12. return 0;
  13. }

我不小心在 if 條件後麵多打了一個分號。現在,如果使用下麵的 gcc 命令來進行編譯,不會生成任何警告。


  1. gcc -Wall test.c -o test

但是如果同時使用 -Wextra 選項來進行編譯:


  1. gcc -Wall -Wextra test.c -o test

會生成下麵這樣一個警告:


  1. test.c: In function main’:
  2. test.c:10:8: warning: suggest braces around empty body in an if statement [-Wempty-body]
  3. if(i);

從上麵的警告清楚的看到, -Wextra 選項從內部啟用了 -Wempty-body 選項,從而可以檢測可疑代碼並生成警告。下麵是這個選項啟用的全部警告標記。

  • -Wclobbered
  • -Wempty-body
  • -Wignored-qualifiers
  • -Wmissing-field-initializers
  • -Wmissing-parameter-type (僅針對 C 語言)
  • -Wold-style-declaration (僅針對 C 語言)
  • -Woverride-init
  • -Wsign-compare
  • -Wtype-limits
  • -Wuninitialized
  • -Wunused-parameter (隻有和 -Wunused 或 -Wall 選項使用時才會啟用)
  • -Wunused-but-set-parameter (隻有和-Wunused-Wall` 選項使用時才會生成)

如果想對上麵所提到的標記有更進一步的了解,請查看 gcc 手冊

此外,遇到下麵這些情況, -Wextra 選項也會生成警告:

  • 一個指針和整數 0 進行 <, <=, >, 或 >= 比較
  • (僅 C++)一個枚舉類型和一個非枚舉類型同時出現在一個條件表達式中
  • (僅 C++)有歧義的虛擬基底
  • (僅 C++)寄存器類型的數組加下標
  • (僅 C++)對寄存器類型的變量進行取址
  • (僅 C++)基類沒有在派生類的複製構建函數中進行初始化

浮點值的等值比較時生成警告

你可能已經知道,浮點值不能進行確切的相等比較(如果不知道,請閱讀與浮點值比較相關的 FAQ)。但是如果你不小心這樣做了, gcc 編譯器是否會報出錯誤或警告?讓我們來測試一下:

下麵是一段使用 == 運算符進行浮點值比較的代碼:


  1. #include<stdio.h>
  2. void compare(float x, float y)
  3. {
  4. if(x == y)
  5. {
  6. printf("\n EQUAL \n");
  7. }
  8. }
  9. int main(void)
  10. {
  11. compare(1.234, 1.56789);
  12. return 0;
  13. }

使用下麵的 gcc 命令(包含 -Wall 和 -Wextra 選項)來編譯這段代碼:


  1. gcc -Wall -Wextra test.c -o test

遺憾的是,上麵的命令沒有生成任何與浮點值比較相關的警告。快速看一下 gcc 手冊,在這種情形下可以使用一個專用的 -Wfloat-equal 選項。

下麵是包含這個選項的命令:


  1. gcc -Wall -Wextra -Wfloat-equal test.c -o test

下麵是這條命令產生的輸出:


  1. test.c: In function compare’:
  2. test.c:5:10: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
  3. if(x == y)

正如上麵你所看到的輸出那樣, -Wfloat-equal 選項會強製 gcc 編譯器生成一個與浮點值比較相關的警告。

這兒是gcc 手冊關於這一選項的說明:

這背後的想法是,有時,對程序員來說,把浮點值考慮成近似無限精確的實數是方便的。如果你這樣做,那麼你需要通過分析代碼,或者其他方式,算出這種計算方式引入的最大或可能的最大誤差,然後進行比較時(以及產生輸出時,不過這是一個不同的問題)允許這個誤差。特別要指出,不應該檢查是否相等,而應該檢查兩個值是否可能出現範圍重疊;這是用關係運算符來做的,所以等值比較可能是搞錯了。

如何更好的管理 gcc 命令行選項

如果在你使用的 gcc 命令中,命令行選項列表變得很大而且很難管理,那麼你可以把它放在一個文本文件中,然後把文件名作為 gcc 命令的一個參數。之後,你必須使用 @file 命令行選項。

比如,下麵這行是你的 gcc 命令:


  1. gcc -Wall -Wextra -Wfloat-equal test.c -o test

然後你可以把這三個和警告相關的選項放到一個文件裏,文件名叫做 gcc-options


  1. $ cat gcc-options&nbsp;
  2. -Wall -Wextra -Wfloat-equal

這樣,你的 gcc 命令會變得更加簡潔並且易於管理:


  1. gcc @gcc-options test.c -o test

下麵是 gcc 手冊關於 @file 的說明:

從文件中讀取命令行選項。讀取到的選項隨之被插入到原始 @file 選項所在的位置。如果文件不存在或者無法讀取,那麼這個選項就會被當成文字處理,而不會被刪除。

文件中的選項以空格分隔。選項中包含空白字符的話,可以用一個由單引號或雙引號包圍完整選項。任何字符(包括反斜杠: '\')均可能通過一個 '\' 前綴而包含在一個選項中。如果該文件本身包含額外的 @file 選項,那麼它將會被遞歸處理。

結論

在這個係列的教程中,我們一共講解了 5 個不常見但是很有用的 gcc 命令行選項: -Save-temps-g、 -Wextra-Wfloat-equal 以及 @file。記得花時間練習使用每一個選項,同時不要忘了瀏覽 gcc 手冊上麵所提供的關於它們的全部細節。

原文發布時間為:2017-12-13

本文來自雲棲社區合作夥伴“Linux中國”

最後更新:2017-06-01 12:02:42

  上一篇:go  2017年關於數據科學六大預言
  下一篇:go  為什麼我們的微信文章版式比較好看?