gcc和g++分别是GUN的C和C++的编译器,gcc和g++在执行编译的时候一般有以下四个步骤:
1.预处理(a.去注释 b.宏替换 c.头文件展开 d.条件编译)–(还是C语言)
2.编译(C代码翻译成->汇编语言)
3.汇编(汇编代码转换成->可重定向二进制目标文件)
4.链接(将汇编过程产生的二进制代码进行链接,将多个.o,.obj 合并形成一个可执行)
gcc只能用来编译C语言,g++可以编译C语言也可以编译C++
没有安装则可使用下面命令进行安装:
sudo yum install -y gcc-c++
gcc -E mytest.c -o mytest.i
gcc -S mytest.i -o mytest.s
gcc -c mytest.s -o mytest.o
gcc mytest.c -o mytest
注意:链接后生成的也是二进制文件
函数库一般分为静态库和动态库两种:
动态链接:
优点:省空间(磁盘的空间,内存的空间),bin体积小,加载速度快。
缺点:依赖动态库,程序可移植性较差。
静态链接:
优点:不依赖第三方库,程序的可移植性较高
缺点:浪费空间
gcc和g++默认生成的二进制程序是动态链接的,我们可以使用file指令进行查看。其次,我们还可以使用ldd指令查看动态链接的可执行文件所依赖的库。
虽然gcc和g++默认采用的是动态链接,但如果我们需要使用静态链接,带上-static选项即可。
gcc test.c -o mytest-s -static
此时生成的可执行文件就是静态链接的了。我们可以查看源代码相同,但链接方式不同而生成的两个可执行程序mytest和mytest-s的大小。这也证明了动态链接比较节省空间,而静态链接比较浪费空间。
你的机器可能因为没有静态库,而导致链接失败!
动态链接必须使用.so动态库文件
sudo yum install -y glibc-static #C静态库
静态链接必须使用.a静态库文件
sudo yum install -y libstdc++-static #C++静态库
在使用make/Makefile前我们首先应该理解各个文件之间的依赖关系以及它们之间的依赖方法。
依赖关系:文件A的变更会影响文件B,那么就称文件B依赖于文件A。
依赖方法:如果文件B依赖于文件A,那么通过文件A得到文件B的方法,就是文件B依赖于文件A的依赖方法。
当你的工程当中有多个源文件的时候,应该如何进行编译生成可执行程序呢?
首先,我们可以直接使用gcc指令对多个源文件进行编译,进而生成可执行程序。
但进行多文件编译的时候一般不使用源文件直接生成可执行程序,而是先用每个源文件各自生成自己的二进制文件,然后再将这些二进制文件通过链接生成可执行程序。
原因
注意:编译链接的时候不需要加上头文件,因为编译器通过源文件的内容可以知道所需的头文件名字,而通过头文件的包含方式(“尖括号”包含和“双引号”包含),编译器可以知道应该从何处去寻找所需头文件。
但是随着源文件个数的增加,我们每次重新生成可执行程序时,所需输入的gcc指令的长度与个数也会随之增加。这时我们就需要使用make和Makefile了,这将大大减少我们的工作量。
步骤一:在源文件所在目录下创建一个名为Makefile的文件。
步骤二:编写Makefile文件
Makefile文件最简单的编写格式是,先写出文件的依赖关系,然后写出这些文件之间的依赖方法,一次写下去。
编写完毕Makefile文件后保存退出,然后在命令行当中执行make指令便可以生成可执行程序,以及该过程产生的中间产物
说明:gcc/g++携带-c选项时,若不指定输出文件的文件名,则默认输出文件名为xxx.o,所以这里也可以不用指定输出文件名。
1.make会在当前目录下找名字为“Makefile”或“”makefile
的文件。
2. 如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。
3. 如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。
4. 如果mytest所依赖的test.o文件不存在,那么make会在Makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。
5. 当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。
6. make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。
makefile是如何得知,我的可执行程序是最新的?
根据文件的最近修改时间来的!
stat mytest
Access:表示文件最近被访问的时间(修改也算访问)
Modify:修改时间(是指文件内容的改变,改变内容其实也会改变文件的属性(大小))
Change:修改时间(是指文件属性的改变,比如权限设置)
源文件的可执行文件一定比新文件的时间要早,make根据这个时间来判断文件是不是最新的,是否需要执行该文件。
在我们每次重新生成可执行程序前,都应该将上一次生成可执行程序时生成的一系列文件进行清理,但是如果我们每次都手动执行一系列指令进行清理工作的话,未免有些麻烦,因为每次清理时执行的都是相同的清理指令,这时我们可以将项目清理的指令也加入到Makefile文件当中。
想clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,但我们可以显示要make执行。
注:一般将这种clean的目标文件设置为伪目标,用.PHONY修饰,伪目标的特性是:总是被执行。
首先,我们来感受一下行缓冲区的存在,在Linux当中以下代码的运行结果是什么样的?
对于此代码,大家应该都没问题,当然是先输出字符串hello 然后休眠1秒之后结束运行。那么对于以下代码呢?
可以看到代码中仅仅删除了字符串后面的‘\n’,那么代码的运行结果还与之前相同吗?答案是否定的,该代码的运行结果是:先休眠3秒,然后打印字符串hello 之后结束运行。该现象就证明了行缓冲区的存在。
显示器对应的是行刷新,即当缓冲区中遇到‘\n’或是缓冲区被写满才会被打印出来,而在第二份代码中并没有‘\n’,所以字符串hello world先被写到缓冲区当中去了,然后休眠3秒后,直到程序运行结束时才将hello打印到显示器当中。
我们在代码中添加fflush(stdout)后就能够实现立马刷新,直接显示hello
这次的结果就是马上输出hello
\r:回车,使光标回到本行行首
\n:换行,使光标下移一格
而我们键盘上的Enter键实际上就等价于\n+\r
既然是\r是使光标回到本行行首,那么如果我们像显示器上写了一个数之后再让光标回到本行行首,然后再写一个数,不就相当于将前面一个数字覆盖了吗?
但这里有一个问题:不使用‘\n’进行换行怎么将缓冲区当中数据打印出来?
这里我们可以使用ffush函数,该函数可以刷新缓冲区,即将缓冲区当中的数据刷新到显示器当中。
对此我们可以编写一个倒计时的程序。