镇江网站设计多少钱,wordpress 防源码抓取,建网站是自己做还是用CMS,湖北高端网站建设学习交流加 个人qq#xff1a; 1126137994个人微信#xff1a; liu1126137994学习交流资源分享qq群#xff1a; 962535112 文章目录1、GCC与gcc2、gcc的幕后工作3、实用的gcc选项3.1、预处理选项-解决宏错误3.2、-S参数-辅助编写汇编程序的好方法3.3、获取系统头文件路径3.4… 学习交流加 个人qq 1126137994个人微信 liu1126137994学习交流资源分享qq群 962535112 文章目录1、GCC与gcc2、gcc的幕后工作3、实用的gcc选项3.1、预处理选项-解决宏错误3.2、-S参数-辅助编写汇编程序的好方法3.3、获取系统头文件路径3.4、产生映射文件3.5、通过选项定义宏3.6、生成依赖关系3.7、指定链接库4、总结 前面的四篇文章终于把处理器系列学完了点击查看上一篇文章高速缓存与TLB。收获很大 接下来就该学习底层软件部分知识。今天学习gcc的基本概念与简单用法。 1、GCC与gcc GCC GNU Compiler Collection GNU 编译器集合包含众多语言的编译器包括C,C,Java等等GCC多用于嵌入式操作系统的编译如LinuxVxWorksAndroid等等 gcc 单指GCC中的C语言编译器 gcc 多用于内核开发以及少数应用程序开发
2、gcc的幕后工作
想了解更多更详细的关于编译链接深层次内容请阅读书籍《CSAPP》第7章与《程序员的自我修养》因为这里我的学习记录只记录结果与常用的几个编译方法。
我们先来看一个简单的程序
test.c源程序
#include stdio.h
#include func.hint g_global 0;
int g_test 1;int main(int argc, char *argv[])
{func();printf(g_global %p\n, g_global);printf(g_test %p\n, g_test);printf(func %p\n, func);printf(main %p\n, main);return 0;
}
func.h头文件
#include stdio.hvoid func()
{
#ifdef TESTprintf(TEST %s\n, TEST);
#endifreturn;
}在Linux下使用gcc进行编译
gcc test.c -o test然后运行
./test结果如下
g_global 0x804a020
g_test 0x804a014
func 0x80483c4
main 0x80483c9很明显上述程序很简单大一的新生都知道为什么。但是今天我们不是学习这个程序的而是想要了解运行 gcc test.c -o test 这个命令后是如何一步一步生成可执行文件test的。
实际上上述C程序从源文件到二进制可执行文件有以下四个步骤
预处理 cppC编译 cc汇编 as链接 ld
大概编译一个源程序为二进制文件的过程如下图所示
当然上面没有列出链接器在生成file.o后还需要将file.o与系统的库文件进行链接生成最终的可执行文件。
从而我们就知道了gcc其实内部包含了预处理器编译器汇编器链接器这四部分。
这四部分这里只是来简单介绍一下网上一大堆本文侧重点不在此
预处理器预处理将源程序的宏定义与带‘#’的部分展开编译器将预处理后得到的文件进行第一次编译得到对应的汇编源程序汇编器将第二步得到的汇编源程序进行第二次编译即汇编得到二进制文件可重定位文件链接器将可重定位文件与相应的库进行链接生成最终的可执行文件
3、实用的gcc选项
本文的重点来了上述的内容过于简单而本节的内容虽然不难但是并不被大多数人所了解所以是本文的重点学习记录。
下面将要学习的gcc选项在工作中具有很强的实用性。
3.1、预处理选项-解决宏错误
gcc -E file.c -o file.i实用上述编译选项 -E 可以得到预处理后的文件有时候我们在程序中定义的宏可能有错误而这种错误又很难找此时如果能得预处理后的文件就可以方便定位错误。
3.2、-S参数-辅助编写汇编程序的好方法
写汇编程序很难但是如果先写成C语言再将这个C语言转化成汇编语言就会很简单。gcc编译工具中-S选项可以达到这个目的。比如以下程序 foo.c程序
#include stdio.hvoid foo(){printf(This is foo().\n); }我们使用如下命令进行编译
gcc -S -O2 foo.c -o foo.s将会生成一个foo.c相同作用的汇编程序foo.s如下 .file foo.c.section .rodata.str1.1,aMS,progbits,1
.LC0:.string This is foo().\n.text.p2align 4,,15
.globl foo.type foo, function
foo:pushl %ebpmovl %esp, %ebpsubl $24, %espmovl $.LC0, 4(%esp)movl $1, (%esp)call __printf_chkleaveret.size foo, .-foo.ident GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5.section .note.GNU-stack,,progbits
使用-S 参数时我们可以根据需要使用-O优化选项。从foo.s的内容可以看出“This is foo().\n” 这个字符串是放在.rodata段的。看来获取C程序对应的汇编代码对C语言实现方面的细节也有所帮助。
3.3、获取系统头文件路径
gcc -v file.c 获取file.c使用的系统头文件的位置
3.4、产生映射文件
如果我们想要知道程序中各个符号的内存布局的信息可以使用如下命令
gcc -Wl,-Mapfile.map file.c -o file3.5、通过选项定义宏
有时候程序中需要的某一个常量会依赖工作环境的不同而改变这个时候我们可以将这个常量定义为宏但是这样我们还是需要每次都在源程序中将宏的值改变这也很麻烦此时就可以利用编译选项 -D在编译的命令行进行宏定义。
还有就是程序中或许会存在下属这样的代码 test.c程序
#include stdio.h
#include func.hint g_global 0;
int g_test 1;int main(int argc, char *argv[])
{func();printf(g_global %p\n, g_global);printf(g_test %p\n, g_test);printf(func %p\n, func);printf(main %p\n, main);return 0;
}test.h头文件
#include stdio.hvoid func()
{
#ifdef TESTprintf(TEST %s\n, TEST);
#endifreturn;
}在头文件中有一处定义 # ifdef TEST …
很明显上面的两个文件都没有定义这个TEST所以程序运行结果如下 g_global 0x804a020g_test 0x804a014func 0x80483c4main 0x80483c9但是可能在某个场合又必须要使用TEST定义那么此时我们肯定不愿意在程序中改来改去此时就利用编译器的 -D选项来定义这个TEST。如下编译命令
gcc -DTESTtest test.c -o test运行程序后结果如下
TEST test
g_global 0x804a020
g_test 0x804a014
func 0x80483c4
main 0x80483e13.6、生成依赖关系
大多数人应该知道make如果不知道也没有关系。 在makefile中make需要通过依赖关系来决定每次构建时哪些文件需要重新编译。使用gcc的-M选项可以得到make所需要的源文件的依赖关系。-MM选项可以让gcc生成不包含系统文件的依赖关系。
比如有如下源文件 main.c源文件main.h与foo.c的内容是什么都行
#include stdio.h
#include main.h
#include foo.cint main(){printf(Hello world!\n);return 0;
}
对其进行如下编译
gcc -M main.c将得到如下输出
可以看到这句是make所需要的main.c的依赖关系。
如果使用如下命令的话
gcc -MM main.c将得到如下输出 结果显而易见
3.7、指定链接库
当一个可执行程序的生成需要使用其他库时需要在链接时加以指定。这就需要用到gcc 的-l与-L选项。
假设一个程序叫做main.c它编译成可执行程序不光需要系统的标准库还需要一个库libfoo.a 且这个libfoo.a与main.c在同一个目录那么在编译main.c时需要以下命令
gcc -o main -L. main.c -lfoo注意
-L告诉gcc编译器当前可以从哪个目录查找库文件此处-L后面跟了一个**点‘.’**表示当前目录。-l选项告诉编译器需要连接的库名。这里并没有写“lib”前缀和“.a后缀”。-lfoo就是代表指定libfoo.a库参与链接。
更加详细的内容参考《程序员的自我修养》
4、总结
今天学习了gcc的简单概念与gcc的常用的参数选项。
本文章参考狄泰软件学院相关课程与《专业嵌入式软件》第4章的内容内容 想学习的可以加狄泰软件学院群 群聊号码199546072
学习探讨加个人 qq1126137994 微信liu1126137994