wordpress博客整站源码,外贸网站建站i,上海专业的网站公,团购网站建立1.Linux编译器-gcc/g使用
1. 预处理#xff08;进行宏替换) 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。 预处理指令是以#号开头的代码行。 实例: gcc –E hello.c –o hello.i 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。 选项“-o”是指目标…1.Linux编译器-gcc/g使用
1. 预处理进行宏替换) 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。 预处理指令是以#号开头的代码行。 实例: gcc –E hello.c –o hello.i 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。 选项“-o”是指目标文件,后面是编译好的文件名 “.i”文件为已经过预处理的C原始程序。 [wwshcss-ecs-d531 ~]$ vim hello.c
[wwshcss-ecs-d531 ~]$ gcc -E hello.c -o hello.i
[wwshcss-ecs-d531 ~]$ cat hello.i 2.编译生成汇编 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。 实例: gcc –S hello.i –o hello.s [wwshcss-ecs-d531 ~]$ gcc -S hello.i -o hello.s
[wwshcss-ecs-d531 ~]$ vim hello.s 3.汇编生成机器可识别代码 汇编阶段是把编译阶段生成的“.s”文件转成目标文件 在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了 实例: gcc –c hello.s –o hello.o [wwshcss-ecs-d531 ~]$ gcc -c hello.s -o hello.o
[wwshcss-ecs-d531 ~]$ vim hello.o 4.连接生成可执行文件或库文件 在成功编译之后,就进入了链接阶段。 实例: gcc hello.o –o hello 生成可执行文件hello 函数库 我们的C程序中并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢? 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用. 函数库一般分为静态库和动态库两种。1.静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”2.动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcchello.o –o hello gcc默认生成的二进制程序是动态链接的这点可以通过 file 命令验证。 gcc -o code_static code.s -static 用static选项链接静态库 yum install -y glibc-static 安装静态库C yum install -y libstdc-static C静态库 2. Linux项目自动化构建工具-make/Makefile makefile带来的好处就是——“自动化编译”一旦写好只需要一个make命令整个工程完全自动编译极大的提高了软件开发的效率。make是一个命令工具是一个解释makefile中指令的命令工具一般来说大多数的IDE都有这个命令比如Delphi的makeVisual C的nmakeLinux下GNU的make。可见makefile都成为了一种在工程方面的编译方法。make是一条命令makefile是一个文件两个搭配使用完成项目自动化构建。 makefile使用
首先先创建两个文件 code.c makefile
-bash-4.2$ ll
total 8
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 64 Aug 19 11:19 makefile -bash-4.2$ ll
total 8
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 64 Aug 19 11:19 makefile
-bash-4.2$ vim code.c
-bash-4.2$ vim makefile
//编译生成可执行程序code
-bash-4.2$ make
gcc -o code code.c
-bash-4.2$ ll
total 20
-rwxrwxr-x 1 wws wws 8360 Aug 19 11:26 code
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 64 Aug 19 11:19 makefile
-bash-4.2$ ./code
hello Makefile!
//删除code
-bash-4.2$ make clean
rm -f code
-bash-4.2$ ll
total 8
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 64 Aug 19 11:19 makefile
makefile原理 我们先了解一下各行代码作用 1.code(目标文件 要生成的文件):code.c 依赖文件列表 可以有多个文件 gcc -o code code.c 依赖关系 Tab键依赖方法 2. .PHONY(声明一个伪目标):clean伪目标名称 clean:依赖文件列表为空 rm -f code 要生成clean文件就要执行它的依赖方法。但它的依赖方法不会生成文件只是执行了删除文件的操作 了解了这些我们看看几个问题 1.为什么make 就可以直接生成code文件呢 (1)makefile文件会被make从上到下扫描第一个目标名是缺省形成的。执行其他组的依赖关系和依赖方法make目标名。 把clean放第一个位置也可以make 默认执行。但不建议 2.PHONY:clean 有什么作用 让目标文件的依赖方法每次都可执行。 -bash-4.2$ ll
total 8
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 64 Aug 19 11:19 makefile
-bash-4.2$ make
gcc -o code code.c
-bash-4.2$ make
make: code is up to date.
-bash-4.2$ make
make: code is up to date.
-bash-4.2$ make
make: code is up to date. 可以看到code:code.c 执行一次就不能执行了。 当我们给code加上.PHONY后 -bash-4.2$ vim makefile
-bash-4.2$ make
gcc -o code code.c
-bash-4.2$ make
gcc -o code code.c
-bash-4.2$ make clean
rm -f code
-bash-4.2$ make clean
rm -f code
-bash-4.2$ make clean
rm -f code 3.可以看到code:code.c可以被多次执行了但为什么clean: 也可以被多次执行呢 让我们先修改一下makefile文件 首先我们要明白什么时候要重新编译文件当然是文件内容被修改的时候。 根据对比code.c 和 code的MtimeModify就可以判断文件内容有没有被修改。 .PHONY就是忽略Mtime时间的对比来让目标文件的依赖方法每次都可执行。 stat 查看文信息 -bash-4.2$ ll
total 20
-rwxrwxr-x 1 wws wws 8360 Aug 19 12:32 code
-rw-r--r-- 1 wws wws 81 Aug 19 11:20 code.c
-rw-rw-r-- 1 wws wws 63 Aug 19 12:32 makefile
//stat 查看文件的详细信息
-bash-4.2$ stat code.cFile: ‘code.c’Size: 81 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1703942 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ wws) Gid: ( 1000/ wws)
//Access 文件最近访问时
Access: 2024-08-19 11:23:32.023200919 0800
//Modify 最新文件内容被修改的时间
Modify: 2024-08-19 11:20:19.100243259 0800
//Change 最新文件属性被修改的时间
Change: 2024-08-19 11:20:19.102243300 0800Birth: -
-bash-4.2$ stat codeFile: ‘code’Size: 8360 Blocks: 24 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1703940 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ wws) Gid: ( 1000/ wws)
Access: 2024-08-19 12:32:42.882419012 0800
Modify: 2024-08-19 12:32:42.882419012 0800
Change: 2024-08-19 12:32:42.882419012 0800Birth: - 让我们修改code.c文件的内容(因为文件属性也包含文件大小内容改变文件属性也会改变所以Ctime和Mtime会一起改变) -bash-4.2$ vim code.c
-bash-4.2$ stat code.cFile: ‘code.c’Size: 180 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1703950 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ wws) Gid: ( 1000/ wws)
Access: 2024-08-19 12:38:49.429946666 0800
Modify: 2024-08-19 12:38:49.429946666 0800
Change: 2024-08-19 12:38:49.431946707 0800Birth: -
-bash-4.2$ stat codeFile: ‘code’Size: 8360 Blocks: 24 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1703940 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ wws) Gid: ( 1000/ wws)
Access: 2024-08-19 12:32:42.882419012 0800
Modify: 2024-08-19 12:32:42.882419012 0800
Change: 2024-08-19 12:32:42.882419012 0800Birth: - 可以看到code.c的Mtime的时间在code Mtime的后面说明code的内容已经不是最新的就可以make 重新编译。 -bash-4.2$ make
gcc -o code code.c
-bash-4.2$ stat codeFile: ‘code’Size: 8360 Blocks: 24 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1703940 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ wws) Gid: ( 1000/ wws)
Access: 2024-08-19 12:41:24.546132682 0800
Modify: 2024-08-19 12:41:24.546132682 0800
Change: 2024-08-19 12:41:24.546132682 0800Birth: - 最后回到为什么clean:可以重复执行就是因为clean:的依赖方法rm没有时间概念所以可以重复执行。 4.我们想输出1111但不想输出echo 1111echo 和字符间的空格不能省怎么关闭命令回显呢 可以用前加关闭 -bash-4.2$ make
echo 1111
1111
echo 1111
1111
echo 1111
1111
echo 1111
1111
gcc -o code code.c -bash-4.2$ make
1111
1111
1111
1111
gcc -o code code.c 虽然看着只是用了一行代码就实现了对code.c的编译其实展开来说这是一个递归实现的过程。 (2)make解析makefile时如果code所依赖的code.o文件不存在那么make会在当前文件中找目标为code.o文件的依赖性以此类推直到如找到再自下而上生成code这有点像一个堆栈的过程 -bash-4.2$ vim makefile
-bash-4.2$ make
gcc -E code.c -o code.i
gcc -S code.i -o code.s
gcc -c code.s -o code.o
gcc code.o -o code
-bash-4.2$ ll
total 48
-rwxrwxr-x 1 wws wws 8360 Aug 20 10:37 code
-rw-r--r-- 1 wws wws 180 Aug 19 12:59 code.c
-rw-rw-r-- 1 wws wws 16978 Aug 20 10:37 code.i
-rw-rw-r-- 1 wws wws 1680 Aug 20 10:37 code.o
-rw-rw-r-- 1 wws wws 538 Aug 20 10:37 code.s
-rw-rw-r-- 1 wws wws 205 Aug 20 10:37 makefile
-bash-4.2$ ./code
hello Makefile!
hello Makefile!
hello Makefile!
hello Makefile!
-bash-4.2$ make clean
rm -f code.i code.s code.o code
-bash-4.2$ ll
total 8
-rw-r--r-- 1 wws wws 180 Aug 19 12:59 code.c
-rw-rw-r-- 1 wws wws 205 Aug 20 10:37 makefile makefile语法 1.% 通配符 $ %.c 把当前目录中后缀.c文件放入依赖文件列表 $ :将依赖文件列表的文件一个一个交给gcc -c 配合 %.o生成同名的.o文件 2.定义变量名 我们可以给目标文件 依赖文件列表定义变量名。 $( ) 用来标记里面内容是变量名不是文件。 3.$^ $ $^:代表依赖文件列表 $:代表目标文件 (3)make默认只生成一个可执行程序 -bash-4.2$ ll
total 12
-rw-rw-r-- 1 wws wws 112 Aug 20 11:40 code.c
-rw-rw-r-- 1 wws wws 181 Aug 20 12:13 makefile
-rw-rw-r-- 1 wws wws 51 Aug 20 12:12 test.c
-bash-4.2$ make
gcc code.c -o code
-bash-4.2$ ll
total 24
-rwxrwxr-x 1 wws wws 8360 Aug 20 12:03 code
-rw-rw-r-- 1 wws wws 112 Aug 20 11:40 code.c
-rw-rw-r-- 1 wws wws 181 Aug 20 12:13 makefile
-rw-rw-r-- 1 wws wws 51 Aug 20 12:12 test.c 可以看到上面这种写法只生成了一个可执行程序怎么才能生成两个呢我们可以用原理(2)让make默认生成all目标文件生成all又需要实现依赖文件列表$(bin1) $(bin2) 实现后all文件什么都不用做就可以同时生成多个可执行程序。 -bash-4.2$ make
gcc code.c -o code
gcc test.c -o test
-bash-4.2$ ll
total 36
-rwxrwxr-x 1 wws wws 8360 Aug 20 12:13 code
-rw-rw-r-- 1 wws wws 112 Aug 20 11:40 code.c
-rw-rw-r-- 1 wws wws 181 Aug 20 12:13 makefile
-rwxrwxr-x 1 wws wws 8360 Aug 20 12:13 test
-rw-rw-r-- 1 wws wws 51 Aug 20 12:12 test.c 补充回车/换行 缓冲区 首先回车和换行是同一个东西吗回车是把光标移动到一行的开头位置换行是把光标从当前位置向下移一格到下一行。 平时我们写程序\n 就是先进行回车再进行换行。 这与缓冲区有什么关系呢 这两段代码生成的程序有什么不同吗 很明显第二段代码输出hello后不会换行。但除此以外第一段代码hello是一开始就会输出但第二段代码会先等2秒再输出。 编译器肯定是自上而下来读代码printf(hello)后hello去哪了其实它是被存在缓冲区了只不过\n可以立刻输出缓冲区的内容立刻输出hello。第二段代码没有\n只能等代码结束或者缓冲区满后输出。 如果我们想让第二段代码缓冲区内容立刻输出有什么办法吗 可以加上fflush(stdout)可以立即将缓冲区内容刷新到输出设备。 注意下面代码输出 i 后进行\r回车操作下一次输出时就会覆盖原位置内容。 但如果覆盖完后后面还有上次留下的内容就会连同新内容一起输出。 比如说上面输出10经过回车操作下次输出的9会覆盖1的位置但后面0仍存在导致后面一直有0。 -2%d 输出两位并左对齐进行解决