1.编译器的编译链接步骤

在学习常用的gcc/g++编译器的命令行参数前,先了解编译器的编译链接过程

  1. 预处理(预编译):将源文件和头文件输入预处理器cpp,输出后缀名为.i或者.ii的文件。预编译过程主要包含这些处理:
    1. 进行宏替换
    2. 处理所有条件编译指令,比如说#ifdef#if#endif#elif#else
    3. 处理预编译指令#include
    4. 删除所有的注释
    5. 保留#pragma once指令,因为这个指令编译器需要使用
    6. 添加行号和文件名标识
  2. 编译:将第一步骤的输出作为cc1plus或者cc1编译器的输入,输出后缀名为.s的汇编代码文件。编译过程主要包含:
    1. 词法分析
    2. 语法分析
    3. 语义分析
    4. 优化
  3. 汇编:将汇编代码由汇编器as处理转换成机器可以执行的指令,通常输出为后缀名为.o或者.obj的文件
  4. 链接:由链接器ld链接上一步产生的目标文件和库,生成可执行程序

note:不指定具体的编译器如cc1plus、cc1的时候,编译器指的是包含预处理器、编译器、汇编器、链接器。

2.gcc/g++编译器的常用命令参数

  1. -E:执行到预处理
//预编译,结果为main.i文件
gcc main.c -E -o main.i
  1. -S:执行源代码到汇编代码的转换
//汇编,结果为main.s
gcc main.c -S
  1. -c:指定编译器的输入
// 指定输入为main.c
gcc -c main.c -o main.o
// 指定输入为main.s
gcc -c main.s -o main.o
  1. -o:指定编译器的输出目标
//目标:生成qq.exe可执行程序(windows下)
gcc main.c -o qq
//目标:生成.i文件
gcc  -E  test.c  -o  test.i    //.i文件
  1. -g或者-ggdb:生成供调试用的可执行文件
gcc main.c -g
  1. -O:编译器对代码进行自动优化编译,输出效率更高的可执行文件
//-O后面还可以跟上数字指定优化级别,常用的数字0-3.
//O0表示不做优化,O1为默认优化
gcc main.c -O2
  1. -W:在编译中开启一些额外的警告(warning)信息
    1. -Werror:要求gcc将所有的警告信息当成错误进行处理.
    2. -Wall:将所有的警告信息全公开
    3. -Wno-deprecated:使用语言废弃的特性,编译器不输出warning
    4. -Wno-strict-aliasing
    gcc main.c -W
    // -Wall:将所有的警告信息全公开
    gcc main.c -Wall
    
  2. -w:关闭所有警告信息
  3. -v/--version:查看编译器版本
  4. -I:编译时指定头文件路径
//main.c文件内容如下:
#include <stdio.h>
#include "log.h"

int main()
{
	printf("logNum:%d\n",logNum);
	return 0;
}
//log.h文件的内容如下
#ifndef _LOG_H_
#define _LOG_H_
const int logNum = 10;
#endif
//main.c与comon文件夹位于同级目录下
//-I指明head.h所在的目录,-o指定生成可执行程序的名称
gcc main.c -I ./comon/ -o qq
  1. -L dirname:指明链接过程中链接程序ld到指定的目录中寻找。
//-L dirname:确定库文件(.so和.a的集合)所在的目录
  1. -lname:链接时装载名为libname.a的函数库。Linux下的库文件在命名时有一个约定,就是应该以 lib 这3个字母开头,由于所有的库文件都遵循了同样的规范,因此在用 -l 选项指定链接的库文件名时可以省去 lib 这3个字母。
例如:-lm 表示链接名为 libm.a 的数学函数库。
  1. -pedantic:当gcc在编译不符合ANSI/ISO C 语言标准的源代码时,将产生相应的警告信息。
//main.c文件内容如下:
#include <stdio.h>
void main(void)
{
    printf("HelloWorld");
    return;
}
//将产生警告信息
gcc main.c -o qq -pedantic
  1. -static:默认情况下,gcc 在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库。
    如果需要的话,可以在编译时加上-static选项,强制使用静态链接库。
  2. -shared:创建后缀名为.so的共享对象文件的时候使用
  3. -save-temps:保存编译过程中生成的一些列中间文件
# gcc test.c -o test -save-temps
除了生成执行文件test之外,还保存了test.i 和 test.s,test.o中间文件,供用户查询调试。
  1. -D选项:在使用gcc或者g++编译器定义宏,语法如下
gcc -D宏名称[=宏值],不指定宏的值则默认为1
  1. -fPIC:编译生成地址无关代码。PIC全称Position-independent Code,编译后缀名为.so的动态库的时候使用这个选项
  2. -pipe:使用管道而不是临时文件
  3. -std:指定项目工程按照什么标准进行后续的处理。例如-std=c++17
  4. -rdynamic

-rdynamic和-Wno-strict-aliasing命令行参数后续补充