编译
        编译过程
                 文件.c->(预处理)->文件.i->(编译)->文件.S->(汇编)->文件.o->(链接)->elf程序
        预处理
                 内容:加载头文件(#include),清除注释(//,./*),替换条件编译(#if #elif #endif    #ifdef),替换宏定义(#define)
                 结果:生成.i文件(gcc -E xx.c -o xx.i)
                 作用:用于debug调试
                 注意:typedef定义由编译器处理
链接库
        静态链接库
                 gcc x.c -o x.o -c
                 只编译不连接,生成.o文件
                 ar打包成 .a文件
                 ar crs lib${func1}.a  ${func1}.o
                 c创建库(不管是否存在)
                 r库中插入模块
                 s创建文件索引,创建较大库时候能加快时间
                 编译:gcc x.c -o x -lx -L.
                 nm查看.a文件中有哪些符号
                 注意:gcc默认是动态库链接,-static强制静态链接指定链接(-lxxx),指定动态库地址(-L)
        动态链接库
                 gcc x.c -o x.o -c -fPIC
                 gcc -o libx.so aston.o -shared 
                 -fPIC位置无关码
                 -shared共享库方式链接
                 指定环境变量LD_LIBRARY_PATH(动态链接库运行时需要被加载)
                 编译:gcc test.c -o test -laston -L.
关键字
        static修饰局部变量,形成静态局部变量,静态局部变量分配在数据段/bss段
         register修饰变量会分配在寄存器,用于提升程序运行效率
         extern声明外部全局变量(变量初始化在其他文件)
         volatile变量不被被编译器改变
         void:p = NULL;  <=> p = (void *)0;即0地址处
        '\0','0',0,NULL
                 '\0'是转义字符,ASCII编码值是0
                 '0'是字符,ASCII编码值是48
                 0是数字
                 NULL是(void *)0
变量
        局部变量分配在栈上,作用域为代码块作用域,生命周期是临时的,连接属性为无连接,定义时未初始化则值随机,变量地址运行时在栈上随机分配地址
         静态局部变量,分配在数据段/bss段(初始化非0在数据段,初始化0或未初始化在bss段),作用域为代码块作用域,生命周期为永久,链接属性为无连接,静态局部变量<==>全局变量
         static使全局变量和函数链接属性由外部转为内部是为解决重名问题,宏和inline函数的链接属性为无连接
宏
        宏定义
                 最值:#define MAX(a,b) (((a)>(b))?(a):(b))
                 一年有多少秒:#define SEC_PER_YEAR  (3652460*60UL)
                 注意:类型默认int,超int类型范围(UL == unsigned int)
        带参宏,带参函数,inline
                 宏定义在预处理期间处理,函数编译处理
                 宏定义在调用处展开,函数在调用处跳转执行,执行完跳回
                 宏定义原地展开,没有调用开销,函数是跳转执行再返回,有较大调用开销
                 带参宏定义不检查参数类型,返回值不附带类型,函数有明确参数类型和返回值类型,调用函数编译会做参数类型检查
                 函数体小适合用带参宏,函数体大用函数调用
                 inline修饰的函数为内联函数,内联函数编译器做参数静态类型检查也不用调用开销而是原地展开
        debug宏
                 #define DEBUG
                 #ifdef DEBUG
                 #define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", FILE, FUNCTION, LINE); fprintf(stderr, VA_ARGS)
                 #else
                 #define DBG(...)
                 #endif
                 __FILE__是预定义宏,在编译的c文件名
                 __FUNCTION__是在编译的函数
                 __LINE__是在编译的行号
                 __VA_ARGS__表示一个或多个参数,类似可变参数中的省略号
                 ...表示参数个数和类型是可变的,…为参数占位符
         内核DEBUG宏
                 #ifdef DEBUG_S3C_MEM
                 #define DEBUG(fmt, args...)   printk(fmt, ##args)
                 #else
                 #define DEBUG(fmt, args...)   do {} while (0)
                 #endif
demo:
debug宏
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif
int main()
{
        DBG("test bug\n");
        return 27;
} 
结果示例:











