第一级:代码调整
代码调整是一种局部的思维方式;基本上不触及算法层级;它面向的是代码,而不是问题; 所以:语句调整,用汇编重写、指令调整、换一种语言实现、换一个编译器、循环展开、参数传递优化等都属于这一级;这个级别试图执行9种单独的优化功能:
-fdefer-pop
-fmerge-constans
-fthread-jumps
-floop-optimize
-fif-conversion: if-then
-fif-conversion2
-fdelayed-branch
-fguess-branch-probability
-fcprop-registers
第二级:新的视角
新的视角强调的重点是针对问题的算法;即选择和构造适合于问题的算法;(冒泡排序还是快排的选择问题是这一级早就应该完成的)很多经典算法都对问题作了一些假设(包括我们当前已经完成的算法实现),而在面对实际问题时“新的视角”提示我们应该重新检视这些假设,并尝试不同的思考问题的角度,寻求适合于问题的新算法; 编译器还试图采用以下几种优化。
10. -fforce-mem
11. -foptimize-sibling-calls
12. -fstrength-reduce
13. -fgcse
14. -fcse-follow-jumps
15. -frerun-cse-after-loop
16. -fdelete-null-pointer-checks
17. -fextensive-optimizations
18. -fregmove
19. -fschedule-insns
20. -fsched-interblock
21. -fcaller-saves
22. -fpeephole2
23. -freorder-blocks
24. -fstrict-aliasing
25. -funit-at-a-time
26. -falign-functions
27. -fcrossjumping
第三级:表驱动状态机
将问题抽象为另一种等价的数学模型或假想机器模型,比如构造出某种表驱动状态机;这一级其实是第二级的延伸,只是产生的效果更加明显,但它有其本身的特点(任何算法和优化活动都可以看作是他的投影);这一级一般可以产生无与伦比的快速程序, 要达到这一级需要大量修炼的;并且思考时必须放弃很多已有的概念或者这些概念不再重要,比如:变量、指针、空间、函数、对象等,剩下的只应该是那个表驱动状态机; 我想把这种境界描述为:空寂中,一些输入驱动着一个带有状态的机器按设定好的最短路线运转着;除此之外have nothing; 既:把解决一个问题的算法看作一个机器,它有一些可变的状态、有一些记忆、有一些按状态运行的规则,然后一些输入驱动这个机器运转;这就是第三级要求的思考优化问题的切入点,也就是寻找一部机器,使它运行经过的路径最短(可能是速度也可能是空间等等) 。编译器还试图采用以下这种优化方式。
28. -finline-functions
29. -fweb
30. -fgcse-after-relo
静态库
(1)制作步骤
1)编译.o文件
2)将.o文件打包:ar rcs libname.a file1.o file2.o file3.o ...
3)将头文件与库一起发布
文件内容及路径分布如下:
[root@centos1 calc]# tree
.
├── include
│ └── head.h
├── lib
├── main.c
└── src
├── add.c
└── sub.c
1 #include
2
3 int add(int a, int b);
4 int sub(int a, int b);
head.h
1 #include “head.h”
2
3 int main(void)
4 {
5 int a = 10, b = 10;
6
7 printf("%d + %d is %d\n", a, b, add(a, b));
8 printf("%d - %d is %d\n", a, b, sub(a, b));
9
10 return 0;
11 }
main.c
1 #include “head.h”
2
3 int add(int a, int b)
4 {
5 return a + b;
6 }
add.c
1 #include “head.h”
2
3 int sub(int a, int b)
4 {
5 return a - b;
6 }
sub.c
编译为.o文件
进入到 src 目录下执行:
[root@centos1 src]# gcc -c *.c -I …/include/
[root@centos1 src]# ll
总用量 16
-rw-r–r--. 1 root root 63 4月 20 14:53 add.c
-rw-r–r--. 1 root root 1240 4月 20 15:10 add.o
-rw-r–r--. 1 root root 63 4月 20 14:24 sub.c
-rw-r–r--. 1 root root 1240 4月 20 15:10 sub.o
将.o文件打包,制作成libCalc.a静态库
[root@centos1 src]# ar rcs libCalc.a *.o
[root@centos1 src]# ll
总用量 20
-rw-r–r--. 1 root root 63 4月 20 14:53 add.c
-rw-r–r--. 1 root root 1240 4月 20 15:10 add.o
-rw-r–r--. 1 root root 2688 4月 20 15:12 libCalc.a
-rw-r–r--. 1 root root 63 4月 20 14:24 sub.c
-rw-r–r--. 1 root root 1240 4月 20 15:10 sub.o
1.动态库 制作步骤
(1)编译与位置无关的代码(下图共享库),生成.o目标文件,关键参数 -fPIC
进程虚拟地址空间
(2)将.o文件打包,关键参数 -shared
(3)将库与头文件一起发布
生成.o目标文件
文件路径和内容同上,进入到src目录,生成.o目标文件:
[root@centos1 src]# gcc -fPIC -c *.c -I …/include/
[root@centos1 src]# ll
总用量 16
-rw-r–r--. 1 root root 63 4月 20 14:53 add.c
-rw-r–r--. 1 root root 1240 4月 20 15:20 add.o
-rw-r–r--. 1 root root 63 4月 20 14:24 sub.c
-rw-r–r--. 1 root root 1240 4月 20 15:20 sub.o
将.o文件打包生成动态库
[root@centos1 src]# gcc -shared -o libCalc.so *.o
[root@centos1 src]# ll
总用量 24
-rw-r–r--. 1 root root 63 4月 20 14:53 add.c
-rw-r–r--. 1 root root 1240 4月 20 15:20 add.o
-rwxr-xr-x. 1 root root 5817 4月 20 15:21 libCalc.so
-rw-r–r--. 1 root root 63 4月 20 14:24 sub.c
-rw-r–r--. 1 root root 1240 4月 20 15:20 sub.o
CMake使用
一、 基本使用
安装:下载二进制包后可直接解压使用
从源码安装则执行命令:./bootstrap; make; make install——尝试执行bootstrap失败
使用:cmake dir_path,生成工程文件或makefile文件
二、 概念
out-of-source build,与in-source build相对,即将编译输出文件与源文件放到不同目录中;
三、 基本结构
1,依赖CMakeLists.txt文件,项目主目标一个,主目录中可指定包含的子目录;
2,在项目CMakeLists.txt中使用project指定项目名称,add_subdirectory添加子目录
3,子目录CMakeLists.txt将从父目录CMakeLists.txt继承设置(TBD,待检验)
四、 语法
#注释
变量:使用set命令显式定义及赋值,在非if语句中,使用${}引用,if中直接使用变量名引用;后续的set命令会清理变量原来的值;
command (args ...) #命令不分大小写,参数使用空格分隔,使用双引号引起参数中空格
set(var a;b;c) <=> set(var a b c) #定义变量var并赋值为a;b;c这样一个string list
Add_executable(${var}) <=> Add_executable(a b c) #变量使用${xxx}引用
条件语句:
if(var) #var 非empty 0 N No OFF FALSE… #非运算使用NOT
…
else()/elseif() … endif(var)
循环语句
Set(VAR a b c)
Foreach(f ${VAR}) …Endforeach(f)
循环语句
WHILE() … ENDWHILE()
五、 内部变量
CMAKE_C_COMPILER:指定C编译器
CMAKE_CXX_COMPILER:
CMAKE_C_FLAGS:编译C文件时的选项,如-g;也可以通过add_definitions添加编译选项
EXECUTABLE_OUTPUT_PATH:可执行文件的存放路径
LIBRARY_OUTPUT_PATH:库文件路径
CMAKE_BUILD_TYPE::build 类型(Debug, Release, …),CMAKE_BUILD_TYPE=Debug
BUILD_SHARED_LIBS:Switch between shared and static libraries
内置变量的使用:
在CMakeLists.txt中指定,使用set
cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF
六、 命令
project (HELLO) #指定项目名称,生成的VC项目的名称;
使用${HELLO_SOURCE_DIR}表示项目根目录
include_directories:指定头文件的搜索路径,相当于指定gcc的-I参数
include_directories (${HELLO_SOURCE_DIR}/Hello) #增加Hello为include目录
link_directories:动态链接库或静态链接库的搜索路径,相当于gcc的-L参数
>> link_directories (${HELLO_BINARY_DIR}/Hello) #增加Hello为link目录
add_subdirectory:包含子目录
>> add_subdirectory (Hello)
add_executable:编译可执行程序,指定编译,好像也可以添加.o文件
>> add_executable (helloDemo demo.cxx demo_b.cxx) #将cxx编译成可执行文件——
add_definitions:添加编译参数
add_definitions(-DDEBUG)将在gcc命令行添加DEBUG宏定义;
add_definitions( “-Wall -ansi –pedantic –g”)
target_link_libraries:添加链接库,相同于指定-l参数
target_link_libraries(demo Hello) #将可执行文件与Hello连接成最终文件demo
add_library:
add_library(Hello hello.cxx) #将hello.cxx编译成静态库如libHello.a
add_custom_target:
message( status|fatal_error, “message”):
set_target_properties( … ): lots of properties… OUTPUT_NAME, VERSION, …
link_libraries( lib1 lib2 …): All targets link with the same set of libs