[TOC]
原文:[15 Most Frequently Used GCC Compiler Command Line Options](https://www.thegeekstuff.com/2012/10/gcc-compiler-options/)以及評論中的一些參數。
> GCC編譯器是一個日常流行的 C 編譯器, 很多Linux的發布版本中都帶有這個編譯器。這篇文章列舉了一些最常用的編譯參數。
本文中使用下面的C語言實現的例子:
```
#include<stdio.h>
int main(void)
{
printf("\n The Geek Stuff\n");
return 0;
}
```
### 1.指定編譯輸出的名字
gcc編譯器最常用的使用格式是:
```
gcc main.c
```
上面的命令執行完整的編譯過程,并且生成一個`a.out`文件。
使用參數`-o`, 可以指定輸出的文件名。
```
gcc main.c -o main
```
上面的命令會產生輸出文件`main`。
為了理解GCC編譯器的完整的編譯過程,可以閱讀[Journey of a C Program to Linux Executable in 4 Stages](https://www.thegeekstuff.com/2011/10/c-program-to-an-executable/)。
### 2.通過`-Wall`參數啟用所有警告
這個參數可以啟用所有警告。
```
#include<stdio.h>
int main(void)
{
int i;
printf("\n The Geek Stuff [%d]\n", i);
return 0;
}
```
上面的代碼編譯時,會出現`未初始化的i`類似的警告。
```
$ gcc - Wall main.c - o main
main.c: In function ‘main’ :
main.c : 6 : 10 : warning : ‘i’ is used uninitialized in this function[-Wuninitialized]
```
### 3.使用`-E`參數只產生預處理輸出
`-E`參數是產生預處理階段的輸出。
```
$ gcc -E main.c > main.i
```
gcc命令將結果輸出在`stdout`中,所以你可以把它重定向到任意的文件中,在上面的例子中,重定向到`main.i`文件中。
### 4.使用`-S`參數只產生匯編代碼
`-S`參數產生匯編級別的代碼。
```
gcc -S main.c > main.s
```
文件`main.s`包含匯編代碼。
### 5.使用`-C`參數只產生編譯的代碼
`-C`參數只產生編譯的代碼(沒有鏈接link)。
1gcc -C main.c
上面的代碼產生`main.o`, 包含機器級別的代碼或者編譯的代碼。
### 6.使用`-save-temps`參數產生所有的中間步驟的文件
`-save-temps`可以做4,5,6步驟的工作。通過這個參數,所有中間階段的文件都會存儲在當前文件夾中,注意它也會產生可執行文件。
```
gcc -save-temps main.c
ls
a.out main.c main.i main.o main.s
```
從例子中我們可以看到各個中間文件以及可執行文件。
### 7.使用`-l`參數鏈接共享庫
`-l`可以用作鏈接共享庫,例如:
1gcc -Wall main.c -o main -lCPPfile
上面的代碼會鏈接`libCPPfile.so`,產生可執行文件`main`。
### 8.使用`-fPIC`產生位置無關的代碼
當產生共享庫的時候,應該創建位置無關的代碼,這會讓共享庫使用任意的地址而不是固定的地址,要實現這個功能,需要使用`-fPIC`參數。
下面的例子產生`libCfile.so`動態庫。
```
gcc -c -Wall -Werror -fPIC Cfile.c
gcc -shared -o libCfile.so Cfile.o
```
產生共享庫的時候使用了`-fPIC`參數。
注意`-shared`產生共享庫。
### 9.使用`-V`打印所有的執行命令
參數`-V`提供詳細的信息,打印出gcc編譯一個文件的時候所有的步驟。
例如:
```
$ gcc -Wall -v main.c -o main
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.6/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
.........
```
這樣我們可以看到所有的細節。
### 10. 使用`-ansi`參數支持 ISO C89程序
使用`-ansi`參數可以支持 ISO C89風格。
比如下面的代碼:
```
#include<stdio.h>
int main(void){
// Print the string
printf("\n The Geek Stuff\n");
return 0;
}
```
使用`-ansi`參數編譯上面的代碼會出錯,因為ISO C89不支持C++風格的注釋。
下面是輸出結果:
```
12main.c: In function ‘main’:
main.c:5:3: error: expected expression before ‘/’ token
```
我們可以看待上面編譯的時候拋出一個注釋錯誤。
### 11.使用`-funsigned-char`將char解釋為符號的char
通過這個參數, char類型被看作為 unsigned char類型。
例子:
```
#include<stdio.h>
int main(void)
{
char c = -10;
// Print the string
printf("\n The Geek Stuff [%d]\n", c);
return 0;
}
```
上面的代碼通過這個參數編譯后,輸出結果為:
```
gcc -Wall -funsigned-char main.c -o main
./main
The Geek Stuff [246]
```
可以看到char是無符號的字節。
### 12.使用`-fsigned-char`將char解釋為有符號的char
和上面的功能相反, 使用這個參數, char類型被看作是有符號的:
```
gcc -Wall -fsigned-char main.c -o main
$ ./main
The Geek Stuff [-10]
```
結果輸出為負數。
### 13. 使用`-D`參數可以使用編譯時的宏
參數`D`可以用作定義編譯時的宏。
例子:
```
#include<stdio.h>
int main(void)
{
#ifdef MY_MACRO
printf("\n Macro defined \n");
#endif
char c = -10;
// Print the string
printf("\n The Geek Stuff [%d]\n", c);
return 0;
}
```
`-D`可以用作從命令行定義宏`MY_MACRO`。
```
$ gcc -Wall -DMY_MACRO main.c -o main
$ ./main
Macro defined The Geek Stuff [-10]
```
可以看到宏被定義了,并打印出了結果。
tput confirms that the macro was defined.
### 14.使用`-Werror`將警告升級為錯誤
通過這個參數,gcc會將所有的警告轉換成錯誤信息。
例子:
```
#include<stdio.h>
int main(void)
{
char c;
// Print the string
printf("\n The Geek Stuff [%d]\n", c);
return 0;
}
```
上面的代碼編譯的時候會有一個`undefined variable c`警告,`-Werror`會把這個警告升級成錯誤。
```
$ gcc - Wall - Werror main.c - o main
main.c: In function ‘main’ :
main.c : 7 : 10 : error : ‘c’ is used uninitialized in this function[-Werror = uninitialized]
cc1 : all warnings being treated as errors
```
### 15.使用`@`參數從文件中讀取參數
gcc參數可以從文件中讀取,通過`@`后跟文件名的方式提供, 多個參數可以使用空格區隔。
例子:
```
cat opt_file
-Wall -omain
```
`opt_file`包含編譯參數。
使用`@`參數:
```
$ gcc main.c @opt_file
main.c: In function ‘main’ :
main.c : 6 : 11 : warning : ‘i’ is used uninitialized in this function[-Wuninitialized]
$ ls main
main
```
輸出結果表明參數的確從文件中讀取了,并且正確的應用到編譯過程中。
> 以下是附加的一些編譯參數
### 16.使用參數`-I`指定頭文件的文件夾
```
gcc -I/home/codeman/include input-file.c
```
`-I-`取消前一個參數功能,一般用在`-Idir`之后。
### 17.使用參數`-std`指定支持的c++/c的標準
```
gcc -std=c++11 hello-world.cpp
```
標準如`c++11, c++14, c90, c89`等。
### 18.使用`-static`生成靜態鏈接的文件
靜態編譯文件(把動態庫的函數和其它依賴都編譯進最終文件)
```
gcc main.c -static -o main -lpthread
```
相反的使用`-shared`使用動態庫鏈接。
### 19.使用`-static-libstdc++`靜態鏈接libstdc++
如果沒有使用`-static`,默認使用libstdc++共享庫,而`-static-libstdc++`可以指定使用libstdc++靜態庫。
### 20.使用`-M`生成文件關聯的信息
```
gcc - M main.c
main.o: main.c / usr / include / stdc - predef.h / usr / include / stdio.h \
/ usr / include / features.h / usr / include / sys / cdefs.h \
/ usr / include / bits / wordsize.h / usr / include / gnu / stubs.h \
/ usr / include / gnu / stubs - 64.h \
/ usr / lib / gcc / x86_64 - redhat - linux / 4.8.5 / include / stddef.h \
/ usr / include / bits / types.h / usr / include / bits / typesizes.h \
/ usr / include / libio.h / usr / include / _G_config.h / usr / include / wchar.h \
/ usr / lib / gcc / x86_64 - redhat - linux / 4.8.5 / include / stdarg.h \
/ usr / include / bits / stdio_lim.h / usr / include / bits / sys_errlist.h
```
### 全部參數介紹
[https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html](https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html)
- 前言
- 服務器開發設計
- Reactor模式
- 一種心跳,兩種設計
- 聊聊 TCP 長連接和心跳那些事
- 學習TCP三次握手和四次揮手
- Linux基礎
- Linux的inode的理解
- 異步IO模型介紹
- 20個最常用的GCC編譯器參數
- epoll
- epoll精髓
- epoll原理詳解及epoll反應堆模型
- epoll的坑
- epoll的本質
- socket的SO_REUSEADDR參數全面分析
- 服務器網絡
- Protobuf
- Protobuf2 語法指南
- 一種自動反射消息類型的 Protobuf 網絡傳輸方案
- 微服務
- RPC框架
- 什么是RPC
- 如何科學的解釋RPC
- RPC 消息協議
- 實現一個極簡版的RPC
- 一個基于protobuf的極簡RPC
- 如何基于protobuf實現一個極簡版的RPC
- 開源RPC框架
- thrift
- grpc
- brpc
- Dubbo
- 服務注冊,發現,治理
- Redis
- Redis發布訂閱
- Redis分布式鎖
- 一致性哈希算法
- Redis常見問題
- Redis數據類型
- 緩存一致性
- LevelDB
- 高可用
- keepalived基本理解
- keepalived操做
- LVS 學習
- 性能優化
- Linux服務器程序性能優化方法
- SRS性能(CPU)、內存優化工具用法
- centos6的性能分析工具集合
- CentOS系統性能工具 sar 示例!
- Linux性能監控工具集sysstat
- gdb相關
- Linux 下如何產生core文件(core dump設置)