0%

Linux中gcc和g++命令

Linux基础(7):Linux中gcc和g++命令

gcc和g++针对程序文件的编译过程、 常用参数、 区别联系等

gcc/g++的安装以及版本查看

1
2
3
4
5
6
7
8
9
#软件安装
sudo apt install gcc g++

#查看版本
gcc -v
g++ -v
gcc --version
g++ --version
#四条指令均可查看版本信息

工作流程

从代码到可执行程序需要经过四个阶段

  • 预处理,主要工作是,展开头文件,宏替换,去除注释行,之后得到后缀为.i文本文件
  • 编译和优化,对文本文件已经编译,得到汇编文件.s后缀
  • 汇编, 对汇编文件进行汇编操作,得到二进制文件.o后缀
  • 链接,将需要调用的库进行链接,得到最终可执行的二进制文件

运用gcc分步对其操作,需要添加一些执行参数

  • 预处理得到.i文件,需要参数-E
  • 编译得到.s汇编文件,需要参数-S
  • 汇编后得到二进制.o文件,需要参数-c
  • 链接得到可执行程序,不需要参数

操作示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#分布操作gcc命令
# 1. 预处理, -o 指定生成的文件名
$ gcc -E test.c -o test.i

# 2. 编译, 得到汇编文件
$ gcc -S test.i -o test.s

# 3. 汇编
$ gcc -c test.s -o test.o

# 4. 链接
$ gcc test.o -o test

# 该命令是直接进行链接生成可执行程序, 链接之前的三步会自动执行
$ gcc test.c -o app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#工程中一步操作,g++为例
gao@gao-VirtualBox:~/桌面/test$ cat hello.cpp
#include <iostream>
using namespace std;

int main(){

//printf("i am vim"\n);
cout<<"i am g++ testing code!"<<endl;
return 0;
}

gao@gao-VirtualBox:~/桌面/test$ g++ hello.cpp -o hello
gao@gao-VirtualBox:~/桌面/test$ ls
d hello hello.cpp hello.i hello.s new_file.txt
gao@gao-VirtualBox:~/桌面/test$ ./hello
i am g++ testing code!

-o后跟输出的文件名

若在-o后不指定输出文件名,会默认生成a.out

常用参数

常用参数图

  • 有关-I的使用,主要针对头文件查询不到的场景

当某个头文件被放置在某个文件夹下,gcc执行预处理时找不到头文件,导致失败。此时可以添加-I参数,额外添加需要引用的头文件路径。

操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -I, 指定头文件目录
$ tree
.
├── add.c
├── div.c
├── include
│   └── head.h
├── main.c
├── mult.c
└── sub.c

# 编译当前目录中的所有源文件,得到可执行程序
$ gcc *.c -o calc
main.c:2:18: fatal error: head.h: No such file or directory
compilation terminated.
sub.c:2:18: fatal error: head.h: No such file or directory
compilation terminated.
#可以看到在当前目录下找不到head.h头文件
#解决办法,额外施加-I参数包含include.h文件

# 可以在编译的时候重新指定头文件位置 -I 头文件目录
$ gcc *.c -o calc -I ./include
  • 有关-D的使用,主要针对后期宏定义的问题

应用需求,当定义一个宏关联很多的日志打印输出,在需要的时候令日志显示,可以在命令执行时,追加宏定义。

1
2
3
4
5
6
7
8
-D 参数的应用场景:
在发布程序的时候,一般都会要求将程序中所有的 log 输出去掉,如果不去掉会影响程序的执行效率,很显然删除这些打印 log 的源代码是一件很麻烦的事情,解决方案是这样的:

将所有的打印 log 的代码都写到一个宏判定中,可以模仿上边的例子
在编译程序的时候指定 -D 就会有 log 输出
在编译程序的时候不指定 -D, log 就不会输出

丙哥的总结,真的精炼。

操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// test.c
#include <stdio.h>
#define NUMBER 3

int main()
{
int a = 10;
#ifdef DEBUG
printf("我是一个程序猿, 我不会爬树...\n");
#endif
for(int i=0; i<NUMBER; ++i)
{
printf("hello, GCC!!!\n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
# 在编译命令中定义这个 DEBUG 宏, 
$ gcc test.c -o app -D DEBUG

# 执行生成的程序, 可以看到程序第9行的输出
$ ./app
我是一个程序猿, 我不会爬树...
hello, GCC!!!
hello, GCC!!!
hello, GCC!!!

#在程序中不指定DEBUG宏,在执行时,通过-D参数来追加宏定义

多文件编译

两种方式

1
2
3
4
5
#第一种罗列出所有的文件
gcc first.c second.c thrid.c -o res

#第二种直接采用通配符
gcc *.c -o res

gcc和g++的区别

关键区别:

1.gcc和g++都可以执行c文件,因为底层都会调用gcc编译器

2.g++和gcc都可以调用c标准库,g++同时可以链接到c++标准库。而gcc想连接到c++标准库需要添加参数 -lstdc++
3._cplusplus宏,两者都可以定义,g++会自动定义。gcc根据文件后缀确定是否定义这个宏。

1
2
3
4
5
6
7
8
9
10
11
12
13
#g++执行c程序
gao@gao-VirtualBox:~/桌面/test$ cat new_test.c
#include <stdio.h>
//using namespace std

int main()
{
printf("g++测试c程序!\n");
return 0;
}
gao@gao-VirtualBox:~/桌面/test$ g++ new_test.c -o n_test
gao@gao-VirtualBox:~/桌面/test$ ./n_test
g++测试c程序!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#gcc执行cpp程序
gao@gao-VirtualBox:~/桌面/test$ cat hello.cpp
#include <iostream>
using namespace std;

int main(){

//printf("i am vim"\n);
cout<<"gcc 运行 cpp文件!"<<endl;
return 0;
}
gao@gao-VirtualBox:~/桌面/test$ gcc hello.cpp -o h -lstdc++
gao@gao-VirtualBox:~/桌面/test$ ./h
gcc 运行 cpp文件!

感谢丙哥:https://subingwen.cn/linux/gcc/