gcc編譯命令—-小話c語言(14)

來源:互聯網
上載者:User

[Mac 10.7.1  Lion  Intel-based  x64  gcc 4.2.1]

Q: 如何讓編譯的檔案可以被gdb調試?

A: 可以加入-g參數。如下代碼,儲存為hello.c: 

#include <stdio.h>int main(){    printf("hello world!\n");    return 0;}

編譯 gcc  hello.c  -o  hello得到hello.

使用  gdb  hello進入調試,輸入list:

可以看到提示沒有符號被載入,這說明上面的編譯命令沒有加入調試資訊,不能被gdb正常調試。

加入-g參數重新編譯  gcc  -g  hello.c  -o  hello得到檔案hello.

gdb  hello進入調試,輸入list:

可以看到,此時已經可以看到原始碼了,接著就可以調試了。

Q: 如何編譯器能讓gprof工具使用?

A: 使用-p參數。不過根據bug列表,intel架構的mac系統不能正常運行gprof, 以後將在ubuntu下將這個例子寫出來。

Q: 如果原始碼的副檔名不是gcc預設支援的副檔名,那麼編譯會出現什麼情況?

A: 將上面的hello.c複製一個為hello.xichen,使用gcc -o hello  hello.xichen編譯:

可以看到出現了問題;可以使用-x參數將檔案當成指定類型的檔案來編譯:

gcc  -x  c  hello.xichen  -o  hello是將hello.xichen當成c代碼編譯:

可以看出已經正確編譯了; -x參數後面可以跟隨c, c++等類型名, 也可以跟隨none來關閉指定為特定類型檔案編譯, 具體請參照gcc協助文檔。

Q: 如果需要測試代碼是否符合ansi標準,怎麼辦?

A: 可以使用-ansi參數。如果是c代碼,它對於不遵循c90標準的代碼將出現編譯問題。

對於//作為注釋,從c99才開始支援,用此作為測試。

#include <stdio.h>int main(){    // c99 support // style comment    printf("hello world!\n");    return 0;}

儲存為hello.c:

gcc  -ansi  -o  hello  hello.c編譯:

使用gcc  -o  hello  hello.c編譯:

可以看到,這樣就沒有問題。

Q: c語言有不同的標準,那麼設定遵循哪種標準使用什麼參數?

A: 可以使用-std=參數格式,可以跟隨c99, gnu99等參數。

Q: 如何禁止將某些關鍵字當做關鍵字?

A: 可以使用-fno-asm參數來禁止asm, inline, typeof當做關鍵字。如下代碼,儲存為hello.c:

#include <stdio.h>inline int add(int a, int b){    return a + b;}int main(){    printf("hello world!\n");    return 0;}

使用gcc  -fno-asm  hello.c  -o  hello編譯:

可以看到出現了編譯錯誤;使用gcc  hello.c  -o  hello編譯:

Q: 有時,有的編譯器將char預設當做有符號的,有的當做無符號的,用編譯器參數可以實現自由控制嗎?

A: 是的。可以使用-funsigned-char或者-fno-signed-char來將char自動當做unsigned類型;類似的,用-fsigned-char或者-fno-unsigned-char來將char自動當做signed類型。例子如下,代碼儲存為unsigned_signed_char.c:

#include <stdio.h>int main(){    char ch = 0xFF;    if(ch < 0)        printf("char is signed...\n");    else        printf("char is unsigned...\n");    return 0;}

使用gcc  unsigned_signed_char.c  -o  unsigned_signed_char編譯運行:

使用gcc  unsigned_signed_char.c  -o  unsigned_signed_char  -funsigned-char編譯運行:

使用 gcc  unsigned_signed_char.c  -o  unsigned_signed_char  -fsigned-char來編譯運行:

Q: 如果有的時候在一個檔案中忘記包含了標頭檔,如何用編譯參數插入標頭檔呢?

A: 可以使用-include參數。代碼如下,儲存為no_header.c:

int main(){    fprintf(stdout, "no header file\n");    return 0;}

使用gcc  no_header.c  -o  no_header編譯:

可以看到,編譯出錯了;改用gcc  no_header.c  -o  no_header  -include  /usr/include/stdio.h編譯:

運行ok:

同樣,可以使用-DXXX或者-DXXX=YYY或者-UXXX或者-undef來定義宏擷取取消定義宏(XXX表示宏名, YYY表示宏定義的字串).

Q: 有時,有個宏在另外一個檔案中,想把它的值作用到另一個檔案中,如何做?

A: 可以使用-imacros 參數; -imacros後面跟著需要包含的宏名的檔案。如下代碼,儲存為imacros.h:

#ifndef IMACROS_H#define IMACROS_H#define N   100double  add(double, double);#endif

如下代碼,儲存為imacros.c(它和上面的imacros.h在同一個目錄下):

#include <stdio.h>int add(int, int);int main(){    int i = N;    printf("i is %d\n", i);    return 0;}

可以看到imacros.c檔案中的N沒有被定義,imacros.h中有它的宏定義。使用gcc  imacros.c  -o  imacros  -imacros  imacros.h編譯:

可以看到編譯ok,且imacros.h中的add函式宣告和imacros.c中的add函式宣告不一致的問題也沒有任何警告,因為-imacros僅僅將imacros.h檔案中的宏進行處理,其它沒有處理。

運行結果:

修改imacros.c代碼如下:

#include <stdio.h>#include "imacros.h"int add(int, int);int main(){    int i = N;    printf("i is %d\n", i);    return 0;}

採用gcc  imacros.c  -o  imacros編譯:

可以看到,編譯出錯了,就是因為add聲明不一致導致的;這裡就可以看出-imacros參數的作用了。

Q: 如果有的時候,為了方便管理,將一些標頭檔移動到另一個目錄,代碼中的標頭檔路徑不想用絕對路徑,命令列參數該如何設定呢?

A: 可以使用-I參數來實現添加額外標頭檔路徑的方式。如下代碼,儲存為include_folder.c:

#include <stdio.h>int main(){    fprintf(stdout, "hello\n");    return 0;}

在hello.c的同目錄下建立如下檔案stdio.h:

#ifndef STDIO_H #define STDIO_H #endif

它基本沒什麼用途。

如果使用gcc  include_folder.c  -o  include_folder編譯沒有任何問題。

如果使用gcc  include_folder.c  -o  include_folder  -I.編譯:

可以看出,編譯出了問題,因為-I.編譯參數將本目錄加入了標頭檔搜尋路徑, 而且是優先在-I指定的路徑下尋找,include_folder.c包含了stdio.h標頭檔,且優先在本目錄下尋找,包含了一個沒有任何用途的標頭檔,導致了後面的編譯錯誤。和-I參數對於標頭檔路徑修改類似的,還有-idirafter, -iprefix, -iwithprefix, -iwithprefixbefore參數。

Q: 如果一個makefile中在當時必須使用-I來包含指定的標頭檔路徑,但是後來因為一些原因又不能繼續使用,有命令可以解決這個問題嗎?

A: 是的。可以使用-I-來取消使用-I參數指定的額外的標頭檔路徑,不過這個參數形式以後可能會廢棄,建議採用-Iquote來代替它。如上面的代碼,使用gcc  include_folder.c  -o  include_folder  -I.  -I-或者gcc  include_folder.c  -o  include_folder  -I.  -iquote都可以正確編譯。

Q: 如果不想使用系統的標頭檔,想直接使用自己編寫的標頭檔,這些標頭檔被儲存在另一個目錄下,怎麼辦?

A: 如下代碼nostdinc.c:

#include <stdio.h>#include <stdlib.h>int main(){    int i = NOSTDINC;    return 0;}

nostdinc.c同目錄下有個標頭檔stdio.h:

#ifndef STDIO_H #define STDIO_H #define NOSTDINC    99#endif

使用gcc  nostdinc.c  -o  nostdinc  -I.  -nostdinc編譯:

可以看出,使用了-nostdinc參數,編譯器將不在系統標頭檔路徑下搜尋, -I.將使得它在本目錄下搜尋,結果沒找到stdlib.h標頭檔,報錯了;可以去掉-nostdinc參數選項,使用gcc  nostdinc.c  -o  nostdinc  -I.編譯即可:

或者nostdinc.c原始碼中將對stdlib.h標頭檔的包含代碼去掉也可以。

Q: 有時需要對原始碼進行預先處理,但是其中的注釋被刪除了,對於分析預先處理後代碼可能有影響,如何讓預先處理過程不刪除注釋?

A: 可以使用-C參數來實現,它一般都和-E參數搭配使用。如下代碼simple_hello.c:

int main(){    // just write something    return 0;}

使用gcc  -E  simple_hello.c預先處理,得到內容:

# 1 "simple_hello.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "simple_hello.c"int main(){ return 0;}

可以看到,注釋被刪除了。

如果採用gcc  -C  -E  simple_hello.c預先處理,得到如下內容:

# 1 "simple_hello.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "simple_hello.c"int main(){ // just write something return 0;}

可以發現注釋依然存在。

Q: 有時我需要查看一個原始碼的依賴關係,如何查看?

A: 可以使用-M參數來獲得。例如,如下代碼,儲存為hello.c:

#include <stdio.h>int main(){    printf("hello, xichen\n");    return 0;}

使用gcc  -M  hello.c得到內容:

hello.o: hello.c /usr/include/stdio.h /usr/include/sys/cdefs.h \  /usr/include/sys/_symbol_aliasing.h \  /usr/include/sys/_posix_availability.h /usr/include/Availability.h \  /usr/include/AvailabilityInternal.h /usr/include/_types.h \  /usr/include/sys/_types.h /usr/include/machine/_types.h \  /usr/include/i386/_types.h /usr/include/secure/_stdio.h \  /usr/include/secure/_common.h

可以看出,hello.c的依賴關係。

類似的還有-MD, -MM, -MMD參數。

Q: 如果希望將一個編譯選項傳遞給gcc內部調用的組譯工具或者連結程式,如何傳遞?

A: 可以使用-Wa,option的方式將option傳遞給組譯工具;可以使用-Wl,option的方式將option傳遞給連結程式。

Q: 有時,我需要產生stabs格式的調試資訊,如何產生?

A: 可以使用-gstabs命令得到,但是它不會產生gdb調試資訊,所以無法再用gdb對產生的可執行檔進行調試。類似的編譯參數還有-gstabs+, -ggdb.

Q: 如果希望使用靜態連結或者動態連結,或者產生一個共用庫,使用什麼參數?

A: 可以使用-static或者-shared參數。但是,在mac系統上,-static基本沒什麼用,-shared參數它不支援。

Q: 如何希望體驗古老的c語言的特性,可以使用什麼參數?

A: 可以使用-traditional參數。具體的例子筆者也寫不出來,寫了幾個看起來很古老的文法,結果gcc都正常給編譯通過了。

Q: 如果需要產生針對某個平台的最佳化代碼,如何辦?

A: 可以使用-O相關的參數進行最佳化,也可以使用-mtune=cpu_type進行具體平台最佳化。

Q: 如果需要不顯示警告資訊或者顯示所有能顯示的警告資訊,如何辦?

A: 可以使用-w參數或者-Wall參數。如下代碼,儲存為warning.c:

#include <stdio.h>void main(){    int i;    printf("hello, xichen\n");}

使用gcc  warning.c  -o  warning編譯:

使用gcc  warning.c  -o  warning  -Wall編譯:


可以看出,包括i沒有被使用的警告也被顯示出來;

使用gcc  warning.c  -o  warning  -w編譯:

可以看到沒有任何警告資訊顯示了。

xichen

2012-5-19 22:26:32

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.