gcc

- 直接输出结果
gcc -Wall hello.c hello
- 系统缺省的头文件目录
\usr\local\include\/usr/include/
- 系统缺省的库文件目录
/usr/local/lib//usr/lib/
gcc中的参数

-M
-M
-
gcc中的-M选项用于生成Makefile的依赖关系列表。这个选项告诉编译器生成一个包含源文件及其依赖的头文件的列表,而不是编译源文件。这对于自动化构建过程非常有用,特别是在大型项目中,确保在修改了某个头文件后,所有依赖它的源文件都能被重新编译。 -
找到依赖项的位置
-v
-vVerbose冗长选项- 在 gcc 编译器中,-v 参数用于显示详细的编译过程信息,包括编译器的版本信息、使用的标准库路径、头文件搜索路径等。这有助于调试编译问题,了解编译器的工作原理,以及诊断编译过程中可能出现的问题。
-c
编译:产生目标文件
- 加入
-cgcc -Wall -c main.c- 后面可以不加入
-o,gcc回自动生成main.o
- 后面可以不加入
-l
-
链接外部库
-
gcc -Wall main.c /usr/lib/libm.a -o calc可以简写为gcc -Wall main.c -lm -o calc -


-
静态库
.lib.a
-L
-L链接库文件的目录
-std
gcc -Wall test.c -o test使用gnu编译gcc -Wall -ansi test.c -o test使用标准c标准编译gcc -Wall -ansi -pedantic test.c严格按照C标准- 可边长数组是GCC的标准不是标准c的标准

gcc -Wall -ansi -D_GNU_SOURCE test.c -o test- 仍然使用标准C编译,但是使用GNU的库
-Wall选项

-Wcomment检测注释是否嵌套


库文件的查找顺序

编译过程

-
预处理
-
编译
-
汇编
-
链接
预处理

- 命令行中可以通过
-D定义宏
- 查看gcc原先就已经定义的宏
cpp -dM /dev/null
-E不想编译,只想看预处理之后的结果gcc -E test.c
gcc -Wall -c -save-temps hello保存所有的中间结果

- 查看gcc原先就已经定义的宏
创建库

-
ar cr-c只编译不链接gcc -Wall -c func1.cgcc -Wall -c func2.car cr libhello.a func1.o func2.o
-
ar -t -
搜索路径
-
gcc -Wall main.c libhello.a -o hello -
注意省略形式的前提时库文件在系统的库文件目录
-
gcc -Wall main.c -L. -lhello -o h2- 通过
-L.指定在当前目录,注意是紧跟着要查找的目录
- 通过
g++

gdb
-g将调试信息保存到目标文件中。gdb ./a.out- run
r运行 - next
n下一个断点 - 打印:print:
p arr[0] - 断点break
b- 在函数处打断点:
b 函数名 - 在哪一行打断点:
b 行数 - 已经在哪些行下打断点了
info b
- 在函数处打断点:
quit退出list查看程序- 进入函数 step
s
gdb调试技巧
-
gdb下可以写shell
shell lsshell cat test.c
-
日志功能呢
set logging on将gdb调试后的输出都输出到gdb.txt中
-
watchpoint
- 观察变量是否变化

-
调试崩掉的程序
-
默认不会生成core文件
- 通过
ulimit -a查看
- 通过
-
打开core文件
ulimit -c unlimited
-
-
调试正在运行的程序
优化
- 关闭返回值优化
-
返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:
当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。而如果稍微做一点优化,就可以将成本降低到一个构造函数的代价,这样就省去了一次拷贝构造函数的调用和依次析构函数的调用。 -
-fno-elide-constructors"
-
源码层次优化


机器码层次优化

gcc如何实现优化

三个等级
- 不优化
-o0-o1- 日常系统设置为
-o2 -o3
makefile
- make是一个命令工具,它解释生成文件设置为中的指令。在生成文件文件中描述了整个工程所有文件的编译顺序、编译规则

hello world
- 语法

a:
@echo "hello world"
输出 hello world
@ 符号用于抑制命令的回显。如果不使用 @,make 会在执行命令之前先打印出命令本身
a:
echo "hello world"
输出
echo “hello world”
hello world
-
make默认编译选择的是第一个a: @echo "hello world" b: @echo "hello b" -
make b编译第二个 -
依赖
a:b @echo "hello world" b: @echo "hello b" c: @echo "hello c输出:
hello b
hello world -
命令
a:b
@echo "hello world"
@ls ./
gcc main.cpp
- 一般我们在执行之前会删除以前生成的文件:
make clean
a:
@echo "11"
clean:
rm -rf a.out
make常用选项

编译流程

calc:
g++ add.cpp sub.cpp multi.cpp calc.cpp -o calc
-
上面这样写不好
calc:add.o sub.o multi.o g++ add.o sub.o multi.o calc.cpp -o calc add.o:add.cpp g++ -c add.cpp -o add.o sub.o:sub.cpp g++ -c sub.cpp -o sub.o multi.o:multi.cpp g++ -c multi.cpp -o multi.o-
输入命令:
make -
执行g++ -c add.cpp -o add.o
g++ -c sub.cpp -o sub.o
g++ -c multi.cpp -o multi.o
g++ add.o sub.o multi.o calc.cpp -o calc -
当只是修改add.c时,输入make,执行
-
g++ -c add.cpp -o add.o
g++ add.o sub.o multi.o calc.cpp -o calc
-
makefile中的变量



TARGET=calc
$(TARGET):add.o sub.o multi.o
g++ add.o sub.o multi.o calc.cpp -o calc
TARGET=calc
OBJ=add.o sub.o multi.o
$(TARGET):$(OBJ)
g++ add.o sub.o multi.o calc.cpp -o calc
add.o:add.cpp
g++ -c $^ -o $@
sub.o:sub.cpp
g++ -c $^ -o $@
multi.o:multi.cpp
g++ -c $^ -o $@
?=条件赋值- ?= 操作符用于条件赋值。它的作用是:如果变量尚未被赋值,则给它赋一个默认值;如果变量已经有一个值,则保持不变

- ?= 操作符用于条件赋值。它的作用是:如果变量尚未被赋值,则给它赋一个默认值;如果变量已经有一个值,则保持不变
Makefile中的伪目标和模式匹配

伪目标
- 引入
calc:add.o multi.o g++ add.o multi.o calc.c -o calc add.o:add.c g++ -c add.c -o add.o multi.o:multi.c g++ -c multi.c -o multi.o clean: rm -rf *.o *.exe - 执行
make clean删除文件.o和.exe - 但是当所在目录中存在文件名为
clean的文件时make: 'clean' is up to date.执行不了
- 加入
.PHONY:clean calc:add.o multi.o g++ add.o multi.o calc.c -o calc add.o:add.c g++ -c add.c -o add.o multi.o:multi.c g++ -c multi.c -o multi.o clean: rm -rf *.o *.exe
模式匹配
.PHONY:clean
OBJ=add.o multi.o calc.o
TARGET=calc
$(TARGET):$(OBJ)
$(CXX) $^ -o $@
add.o:add.c
$(CXX) -c $^ -o $@
multi.o:multi.c
$(CXX) -c $^ -o $@
calc.o:calc.c
$(CXX) -c $^ -o $@
clean:
rm -rf *.o *.exe
- 加入通配符之后
.PHONY:clean OBJ=add.o multi.o calc.o TARGET=calc $(TARGET):$(OBJ) $(CXX) $^ -o $@ %.o:%.c $(CXX) -c $^ -o $@ clean: rm -rf *.o *.exe
wildcard 与pastsubst

- 在 Makefile 中,wildcard 函数用于查找匹配给定模式的所有文件名。这对于自动收集源文件列表特别有用,这样就不必手动列出所有的文件。wildcard 函数返回一个空格分隔的字符串,其中包含所有匹配模式的文件名。

- patsubst


makefile中编译动态链接库

动态链接库的名字:
SoTest.cc libSoTest.so
-
生成动态链接库:
g++ -shared -fPIC .\SoTest.cc -o libSoTest.so或者g++ -shared -fPIC .\SoTest.cpp -o libSoTest.dll注意在windows下应该生成.dll -
编译并生成共享库
g++ -shared -fPIC SoTest.cpp -o libSoTest.so -
编译并链接 test.cpp:
g++ test.cpp -o test -L. -lSoTest

-
法1:
- 假设你的 libSoTest.so 在当前目录下,你可以使用以下命令:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./test

- makefile
test:libSoTest.so $(CXX) -lSoTest -L./ test.cpp -o test libSoTest.so: $(CXX) -fPIC -shared SoTest.cpp -o libSoTest.so clen: $(RM) *.so test
makefile中编译静态链接库

- 输出目标文件
g++ -c aTest.cc -o aTest.o
- 生成静态链接库
ar -r libaTest.a aTest.o
g++ main.cpp -o main -L./static -laTest- 以下编译不通过(注意-l和-L在后面)
-
g++ -laTest -L./static main.cpp -o main
-

-
修改之后依然可以运行

-
但是动态链接库修改了就不能运行
-

-


makefile的编写
libaTest:
${CXX} -c aTest.cpp -o aTest.o
${AR} -r libaTest aTest.o
clean:
${RM} *.o *.a

- 简写
TARGET=main
LDFLAGS=-L./static
LIBS=-laTest
${TARGET}:
# ${CXX} main.cpp -o main -laTest -L./static
${CXX} main.cpp -o ${TARGET}
Makefile运行流程

静态库
- Linux 是
.a.windos是.lib

动态库
- Linux 是
.so.windos是.dll










3255

被折叠的 条评论
为什么被折叠?



