GCC編譯器(2)


GCC編譯器(1)

4、警告選項

在編譯過程中,編譯器的報錯和警告信息對於程序員來說是非常重要的信息,GCC包含完整的出錯檢查和警告提示功能,它可以幫助Linux程序員盡快找出錯誤的或潛在的錯誤代碼,從而寫過更優美的代碼。GCC的編譯器警告選項如下表:

類型 說明
-Wall 啟用所有警告信息
-Werror 在發生警告時取消編譯操作,即將警告看作是錯誤
-w 禁用所有警告信息

 

下面看一段代碼,使用GCC編譯,同時開啟警告信息:

#include <stdio.h>
void main ()
{
	int x;
	for(x=1;x<=10;x++)
	{
		printf("%d\n",x);
	}
}

對上面的代碼進行編譯連接:

$ gcc -Wall example3.c -o example3

example3.c:2:6: 警告: ‘main’的返回類型不是‘int’ [-Wmain]

從上面的輸出看到,GCC給出了警告信息,意思是main函數的返回值被聲明為void,但實際應該是int。

此外,GCC還提供了許多以-W開頭的選項,允許用戶指定輸出某個特定的警告,例如:

  • -Wcomment:出現注釋嵌套時發出警告。
  • -Wconversion:如果程序中存在隱式類型轉換,則發出警告。
  • -Wformat:檢查printf和scanf等格式化輸入輸出函數的格式字符串和參數類型的匹配情況,如果發現不匹配則發出警告。
  • -Winline:如果函數不能被內聯,則發出警告。
  • -Wlong-long:如果使用了long long型數據,則發出警告。
  • -Wmain:如果main函數的返回類型不是int型,或者調用main函數時使用的參數數目不正確,則發出警告。
  • -Wmissing-declarations:如果定義了全局函數,但卻沒有在頭文件中聲明,則發出警告。
  • -Wparentheses:在某些情況下,如果忽略掉了括號,則會發出警告。
  • -Wreturn-type:如果函數定義了返回類型,而默認類型是int型,編譯器會發出警告。
  • -Wuninitialized:如果使用的自動變量沒有被初始化,則發出警告。
  • -Wundef:如果在#if宏中使用了未定義的變量做判斷,則發出警告。
  • -Wunused:如果聲明的變量或static型函數沒有使用,則發出警告。

下面使用GCC編譯一段程序,來說明開啟警告信息的必要性:

#include<stdio>
int main()
{
	double x;
	printf("%d\n",x);  /* 這里將%f誤輸為%d */
	return 0;
}

對上面的程序進行編譯:

$ gcc example4.c -o example4

可以看到,編譯並沒有報錯,運行可執行文件,輸出結果為:

$ ./example4

134513689

這不是想要的輸出結果,如果在上面的編譯中加入-Wformat或-Wall選項,即:

$ gcc -Wformat example4.c -o example4

$ gcc -Wall example4.c -o example4

GCC給出如下警告信息:

example4.c: 在函數‘main’中:

example4.c:5:5: 警告: 格式 ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Wformat]

格式字符串和參數類型的不匹配會導致程序運行錯誤,所以這是是非常有用的警告選項。

下面使用GCC編譯一段程序,使用-Wparentheses選項對其中的括號進行檢查。

#include<stdio>
int main()
{
	int a=1;
	int b=0;
	int c=1;
	if(a&&b||c)
	{
		;
	}
	if(a==1)
		if(b==1)
			printf("b=1\n");
	else
		printf("b!=1\n");
	return 0;
}

 

對上面的程序進行編譯:

$ gcc -Wparentheses example5.c -o example5

example5.c: 在函數‘main’中:

example5.c:7:5: 警告: 建議在‘||’的操作數中出現的‘&&’前后加上括號 [-Wparentheses]

example5.c:11:7: 警告: 建議顯式地使用花括號以避免出現有歧義的‘else’ [-Wparentheses]

所以GCC編譯器的警告選項對程序員來說是非常重要的。

 

5、連接選項

GCC編譯器提供的連接器選項如下表:

類型 說明
-Idirectory 向GCC的頭文件搜索路徑中添加新的目錄
-Ldirectory 向GCC的庫文件搜索路徑中添加新的目錄
-llibrary 提示連接程序在創建可執行文件時包含指定的庫文件
-static 強制使用靜態鏈接庫
-shared 生成動態庫文件

 

先來理解一下頭文件和庫文件這兩個概念:

頭文件包含變量和函數的聲明,但沒有定義函數的實現。函數的具體實現實在庫文件中完成的,庫文件可分為靜態庫和動態庫,靜態庫是指編譯連接時,將庫文件的代碼全部加入到可執行文件中,這樣運行時就不需要庫文件了。靜態庫的后綴名一般為“.a”。動態庫是指在編譯連接時並不將庫文件的代碼加入到可執行文件中,而是在程序執行時由運行時連接文件加載庫文件,這樣可以節省系統的開銷。動態庫的后綴名一般為“.so”。

例如我們編譯是用-I選項來指定頭文件的路徑:

$ gcc example.c –o example –I/home/xxx/include

頭文件所對應的庫文件,如果沒有特別指定時,GCC會到默認的搜索路徑進行查找。

使用-L選項來指定庫文件的路徑,例如:

$ gcc example.c –o example –L/home/xxx/lib

GCC編譯器在默認情況下使用動態庫,但如果使用了-static選項,連接器將忽略動態庫,強制使用靜態鏈接庫,即使用如下命令:

$ gcc example.c –o example –static –lm

此時靜態庫文件中的代碼全部包含到可執行文件中,所以生成的可執行文件比較大。

 

 

本節完…


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM