linux 编程基础知识小结
一.编译
linux .c文件编译成可执行文件,需要经过预处理,编译,汇编,链接的过程,我们现在分别介绍每个过程,我们一般说的编译就是这四个过程的统称。
1.预处理
命令:gcc -E test.c -o test.i
在源文件中,我们把以#开头的叫做预处理命令,也就是说预处理就是处理文件中#开头的一些命令,他包括头文件包含#include,宏定义#define,条件编译,在linux开发过程这一步我们可以做许多应用。
检查功能宏的定义,没有定义可以让预处理阶段就报错报,或者检查某段代码有没有被编译进去。
#include <stdio.h>
#include <stdlib.h>
//#define BUILD_TEST
int main(int argc, const char *argv[])
{
int i = 0;
#ifndef BUILD_TEST
#error not define BUILD_TEST!!!!
#endif
#ifdef BUILD_TEST
printf("this is test \n");
#endif
return 0;
}
从代码可以看出没有定义功能宏,预处理就报错了,或者检查某段代码有没有编译进去直接代码中添加#error即可。
2.编译
命令:gcc -S test.c -o test.s
编译的过程就是将.i 翻译汇编语言
3.汇编
命令: gcc -c test.c -o test.o
将第二步代码翻译成机器能够认识的机器代码,最终生成的elf文件(obj文件)
4.连接
命令: gcc -o file
将上一步的obj文件 系统的库文件 编译生成的库文件连接起来,最终生成平台可以支持的可执行文件(平台,注意使用该平台的交叉编译工具链编译)
上面的整个过程就是c编译的过程。
二.常用编译选项
1.-Wall
这个编译选项可以打印出代码中所有的警告信息
2.-Werror
在实际程序开发中,一般我们是不允许警告的存在,我们需要把警告当错误处理
上面二者的区别在于 警告可以生成可执行程序,错误不能生成可执行程序
3.-g
我们应用程序调试中,经常需要遇到gdb调试,所有我们如果要生成的可执行程序支持gdb调试,必须要加入-g 选项编译。
下面我们对比下加-g与不加-g的区别
带不带-g 因为可执行程序中带有调试信息,所以文件大小有个很大的区别
4.-static
用静态库来编译这个文件
下面我们比较下带与不带的区别
文件大小有个明显的区别,因为我们知道如果使用静态库,我们需要把依赖的函数等编译到可执行程序中,所以造成文件很大。
5.-shared
用于生成动态库
生成静态库的方法,先编译生成.o文件,后使用
下面比较下.a 与.so文件
三.常用的linux命令
1.file 命令
查询文件类型,上面多次应用了
2.readelf
读取elf文件头
3.strings
查找elf中的字符串
4.ldd
查看连接的动态库
5.nm
查看符号表 -主要是新增加的函数与全局变量有没有编译进去
查找main函数
6.sum md5sum
文件校验相关,比较文件是否有变化