C理解(五):编译,链接库,宏,关键字,变量

编译

        编译过程
                文件.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 

#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;
}

结果示例:

你可能感兴趣的:(c语言)