• 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宏

    1. #include
    2. #define DEBUG
    3. #ifdef DEBUG
    4. #define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
    5. #else
    6. #define DBG(...)
    7. #endif
    8. int main()
    9. {
    10. DBG("test bug\n");
    11. return 27;
    12. }

    结果示例:

  • 相关阅读:
    本周大新闻|7-11便利店测试AR远程购物,PICO商店支持退款
    PHP-数组声明、相关函数与遍历
    卷积神经网络处理图像,卷积神经网络图像增强
    【C语言刷LeetCode】395. 至少有 K 个重复字符的最长子串(M)
    ESP8266-Arduino编程实例-MCP23017并行IO扩展驱动
    Ubuntu16.04 python matplotlib 输出轴标签出现中文乱码
    eclipse / sts 设置类注释模板
    05 面向对象
    [附源码]Python计算机毕业设计Django的物品交换平台
    全局多项式(趋势面)与IDW逆距离加权插值:MATLAB代码
  • 原文地址:https://blog.csdn.net/tyro_wzp/article/details/133419885