学习GCC编译器的推荐图书是:An Introduction to GCC(有中文版和英文版 可下载)和Using GCC (gcc的官方手册)
- gcc默认是用GNU C的标准编译程序的,如果要指定用ANSI标准时:gcc -ansi 指定用c99或者其他版本的标准:gcc -std=c99
- C的标准:ANSI C标准或者叫做ISO C或ANSI/ISO C 有--C89(1989年),C90(1990年),C99(1999年) 最近好像颁布了C11(2011年)
- gcc 的预编译器cpp中预先定义了很多宏可用命令:cpp -dM /dev/null查看,有时代码预编译时可以用事先定义好的宏开关来控制是否编译(条件编译):
#if TEST printf("TEST is defined!");
#endif
--编译时如果是:gcc -DTEST (默认值为1)则以上代码被编译,否则将不会编译上面的代码。也可以赋值:gcc -DTEST=value
- gcc -c -Wall -save-temps hello.c会产生hello.c外还会把编译过程的临时文件保存下来(如hello.i,hello.s)
- gcc -g -Wall hello.c会加入调试信息在可执行文件中(a.out),便于调试--gdb a.out。如果程序出错OS会产生一个core dump文件“core.pid”(如core.2027),但是为了避免程序错误而产生大量core dump文件占满硬盘空间OS(如Linux)默认不让产生,可用"ulimit -c"命令查看(结果是0)但可以用"ulimit -c unlimited"解除(具体可man ulimit)。用gdb分析调试:gdb a.out core.2027 来分析。(学习gdb的用法!)
- 编译优化:加快执行速度,减小代码尺寸。源码优化(source-level Optimization)+机器码的优化
"
time ./a.out" --计算a.out运行时间
源码优化:
1.子表达式消除(common subexpression elimination--CES)
例:m=cos(a) + sin(b/2) + (1 + cos(a) +sin(b/2))//多次调用相同表达式
==>t=cos(a); n=sin(b/2); m=t+n+(1+t-n);
2.函数内连(function inlining--FL)多次调用一些小函数增加了程序的调用时间(用inline关键字)
例:double sq(double x)
{
return(x*x);
}
sum=0;
for(i=0;i<10000;i++)
{
sum +=sq(i+0.5);
}//函数的不断调用增加开销,而函数执行的时间却很少
==> inline double sq(double x)
{
return(x*x);
}
sum=0;
for(i=0;i<10000;i++)
{
sum +=sq(i+0.5);
}
空间换时间--增加代码的尺寸来加快程序的执行速度
- Debug:建议在debug时关闭优化选项 gcc -Wall -g -O0 test.c 打开优化时可能还会发现一些未打开优化时的warning
例:void sign(int x) {
int n;
if(x>0) n=1;
else if(x<0) n=-1;
}//未考虑到x=0的情况,不优化时不会发现错误,但打开优化时会发现错误
- 编译器的工作原理(How the compiler works)
1.预处理preprocessing(to expand macros)--
CPP2.编译Compilation(from source code to assembly--汇编 language)--GCC
3.汇编Assembly(from assembly language to machine code)--AS
4.链接(to creat the final executable)--LD
- 辅助命令:file--可查看.o文件或者可执行文件的属性
ELF~Executable and Linking Format可执行文件
LSB~小端存储 X86(AMD Intel)
MSB~大端存储 motorola 68K
not stripped~未去除符号表(调试信息)可用strip命令去除"strip a.out",用nm查看符号表"nm a.out" ,查看a.out需要的运行时库:"ldd a.out"
- 编译器相关工具(compiler-related tools)
- gprof 可以分析程序的性能便于对相关函数进行优化:gcc -Wall -pg cov.c ; ./a.out(此时会产生gmon.out文件);gprof a.out(读取gmon.out+a.out来分析性能)
- gcov 覆盖度分析:"gcc -Wall -fprofile-arcs -ftest-coverage cov.c"(会产生cov.gcno);“./a.out”(会此时cov.gcda) ; "gcov cov.c"(gcov的是源程序!此时产生cov.c.gcov文件)cov.c.gcov中行前有"#####"表示语句从未执行过
阅读(3486) | 评论(0) | 转发(0) |